# Configuration options
default_statetrackers = 'mesa'
+default_targets = 'none'
if common.default_platform in ('linux', 'freebsd', 'darwin'):
default_drivers = 'softpipe,failover,svga,i915,i965,trace,identity,llvmpipe'
opts.Add(ListVariable('winsys', 'winsys drivers to build', default_winsys,
['xlib', 'vmware', 'i915', 'i965', 'gdi', 'radeon', 'graw-xlib']))
+opts.Add(ListVariable('targets', 'driver targets to build', default_targets,
+ ['dri-i915',
+ 'dri-i965',
+ 'dri-nouveau',
+ 'dri-radeong',
+ 'dri-swrast',
+ 'dri-vmwgfx',
+ 'egl-i915',
+ 'egl-i965',
+ 'egl-nouveau',
+ 'egl-radeon',
+ 'egl-swrast',
+ 'egl-vmwgfx',
+ 'graw-xlib',
+ 'libgl-gdi',
+ 'libgl-xlib',
+ 'xorg-i915',
+ 'xorg-i965',
+ 'xorg-nouveau',
+ 'xorg-radeon',
+ 'xorg-vmwgfx']))
+
opts.Add(EnumVariable('MSVS_VERSION', 'MS Visual C++ version', None, allowed_values=('7.1', '8.0', '9.0')))
env = Environment(
import os
import os.path
+import re
import subprocess
import sys
import platform as _platform
'ppc' : 'ppc',
'x86_64': 'x86_64',
}
+
+
+# find default_machine value
if 'PROCESSOR_ARCHITECTURE' in os.environ:
default_machine = os.environ['PROCESSOR_ARCHITECTURE']
else:
default_machine = _platform.machine()
default_machine = _machine_map.get(default_machine, 'generic')
+
+# find default_llvm value
if 'LLVM' in os.environ:
default_llvm = 'yes'
else:
+ # Search sys.argv[] for a "platform=foo" argument since we don't have
+ # an 'env' variable at this point.
+ platform = default_platform
+ pattern = re.compile("(platform=)(.*)")
+ for arg in sys.argv:
+ m = pattern.match(arg)
+ if m:
+ platform = m.group(2)
+
default_llvm = 'no'
try:
- if subprocess.call(['llvm-config', '--version'], stdout=subprocess.PIPE) == 0:
+ if platform != 'windows' and subprocess.call(['llvm-config', '--version'], stdout=subprocess.PIPE) == 0:
default_llvm = 'yes'
except:
pass
+
+# find default_dri value
if default_platform in ('linux', 'freebsd'):
default_dri = 'yes'
elif default_platform in ('winddk', 'windows', 'wince', 'darwin'):
darwin* )
LIB_EXTENSION='dylib' ;;
cygwin* )
- LIB_EXTENSION='dll' ;;
+ LIB_EXTENSION='dll.a' ;;
aix* )
LIB_EXTENSION='a' ;;
* )
#endif
+#ifndef EGL_NOK_texture_from_pixmap
+#define EGL_NOK_texture_from_pixmap 1
+
+#define EGL_Y_INVERTED_NOK 0x307F
+#endif /* EGL_NOK_texture_from_pixmap */
+
+
#ifdef __cplusplus
}
#endif
INCLUDE_DIRS = -I$(TOP)/include $(X11_CFLAGS)
HEADERS = $(TOP)/include/GLES/egl.h
-LIB_DEP = $(TOP)/$(LIB_DIR)/libEGL.so
+LIB_DEP = $(TOP)/$(LIB_DIR)/$(EGL_LIB_NAME)
-LIBS = -L$(TOP)/$(LIB_DIR) -lEGL -lGL -lm
+LIBS = -L$(TOP)/$(LIB_DIR) -l$(EGL_LIB) -l$(GL_LIB) -lm
EGLUT_DIR = $(TOP)/progs/egl/eglut
#include "eglut.h"
+#ifndef M_PI
+#define M_PI 3.14159265
+#endif
+
static GLfloat view_rotx = 20.0, view_roty = 30.0, view_rotz = 0.0;
static GLint gear1, gear2, gear3;
static GLfloat angle = 0.0;
ES1_LIB_DEPS = \
- $(TOP)/$(LIB_DIR)/libEGL.so \
- $(TOP)/$(LIB_DIR)/libGLESv1_CM.so
+ $(TOP)/$(LIB_DIR)/$(EGL_LIB_NAME) \
+ $(TOP)/$(LIB_DIR)/$(GLESv1_CM_LIB_NAME)
ES1_LIBS = \
- -L$(TOP)/$(LIB_DIR) -lEGL \
- -L$(TOP)/$(LIB_DIR) -lGLESv1_CM $(LIBDRM_LIB) $(X11_LIBS)
+ -L$(TOP)/$(LIB_DIR) -l$(EGL_LIB) -l$(GLESv1_CM_LIB) \
+ $(LIBDRM_LIB) $(X11_LIBS)
EGLUT_DIR = $(TOP)/progs/egl/eglut
#include <EGL/egl.h>
+#ifndef M_PI
+#define M_PI 3.14159265
+#endif
static int WinWidth = 300, WinHeight = 300;
#include <EGL/egl.h>
+#ifndef M_PI
+#define M_PI 3.14159265
+#endif
+
static int TexWidth = 256, TexHeight = 256;
static int WinWidth = 300, WinHeight = 300;
#include "eglut.h"
+#ifndef M_PI
+#define M_PI 3.14159265
+#endif
+
static const struct {
GLenum internalFormat;
const char *name;
ES2_LIB_DEPS = \
- $(TOP)/$(LIB_DIR)/libEGL.so \
- $(TOP)/$(LIB_DIR)/libGLESv2.so
+ $(TOP)/$(LIB_DIR)/$(EGL_LIB_NAME) \
+ $(TOP)/$(LIB_DIR)/$(GLESv2_LIB_NAME)
ES2_LIBS = \
- -L$(TOP)/$(LIB_DIR) -lEGL \
- -L$(TOP)/$(LIB_DIR) -lGLESv2 $(LIBDRM_LIB) $(X11_LIBS) \
+ -L$(TOP)/$(LIB_DIR) -l$(EGL_LIB) -l$(GLESv2_LIB) \
+ $(LIBDRM_LIB) $(X11_LIBS)
PROGRAMS = \
es2_info \
#include <EGL/eglext.h>
#include "eglut.h"
+#ifndef M_PI
+#define M_PI 3.14159265
+#endif
+
struct gear {
GLfloat *vertices;
GLuint vbo;
#include <EGL/egl.h>
+#ifndef M_PI
+#define M_PI 3.14159265
+#endif
+
#define FLOAT_TO_FIXED(X) ((X) * 65535.0)
TOP = ../../..
include $(TOP)/configs/current
-VG_LIBS=-lm -lEGL -lOpenVG -L$(TOP)/lib -L$(TOP)/lib/gallium
+VG_LIBS=-lm -L$(TOP)/$(LIB_DIR) -l$(EGL_LIB) -l$(VG_LIB)
INCLUDE_DIRS = -I$(TOP)/include $(X11_CFLAGS)
EGLUT_DIR = $(TOP)/progs/egl/eglut
--- /dev/null
+#version 120
+const int KernelSize = 16;
+uniform float KernelValue1f[KernelSize];
+
+
+float add_two(float a, float b)
+{
+ if (a > b)
+ return a - b;
+ else
+ return a + b;
+}
+
+vec4 func(vec4 x)
+{
+ int i;
+ vec4 tmp = gl_Color;
+ vec4 sum = x;
+
+ for (i = 0; i < KernelSize; ++i) {
+ sum = vec4( add_two(sum.x, KernelValue1f[i]) );
+ }
+ return sum;
+}
+
+void main(void)
+{
+ vec4 sum = vec4(0.0);
+
+ sum = func(sum);
+ gl_Position = gl_Vertex;
+ gl_FrontColor = sum;
+}
--- /dev/null
+#version 120
+const int KernelSize = 16;
+uniform float KernelValue1f[KernelSize];
+
+
+float add_two(float a, float b)
+{
+ if (a > b)
+ return a - b;
+ else
+ return a + b;
+}
+
+vec4 myfunc(vec4 x, vec4 mult, vec4 c)
+{
+ if (x.x >= 0.5) {
+ return mult * c;
+ } else {
+ return mult + c;
+ }
+}
+
+vec4 func2(vec4 x)
+{
+ int i;
+ vec4 color = vec4(0);
+ for (i = 0; i < KernelSize; ++i) {
+ vec4 tmp = vec4(1./KernelSize);
+ color += myfunc(x, tmp, gl_Color);
+ }
+ return x * color;
+}
+
+vec4 func(vec4 x)
+{
+ int i;
+ vec4 tmp = gl_Color;
+ vec4 sum = x;
+
+ for (i = 0; i < KernelSize; ++i) {
+ sum = vec4( add_two(sum.x, KernelValue1f[i]) );
+ }
+ sum = func2(sum);
+ return sum;
+}
+
+void main(void)
+{
+ vec4 sum = vec4(0.0);
+
+ sum = func(sum);
+ gl_Position = gl_Vertex;
+ gl_FrontColor = sum;
+}
#define GLX_GLXEXT_PROTOTYPES
+#include <assert.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <GL/gl.h>
int accumRedSize, accumGreenSize, accumBlueSize, accumAlphaSize;
int numSamples, numMultisample;
int visualCaveat;
+ int floatComponents;
+ int srgb;
};
return "rgba|ci";
default:
return "";
- }
+ }
+}
+
+static const char *
+caveat_string(int caveat)
+{
+ switch (caveat) {
+#ifdef GLX_EXT_visual_rating
+ case GLX_SLOW_VISUAL_EXT:
+ return "Slow";
+ case GLX_NON_CONFORMANT_VISUAL_EXT:
+ return "Ncon";
+ case GLX_NONE_EXT:
+ /* fall-through */
+#endif
+ case 0:
+ /* fall-through */
+ default:
+ return "None";
+ }
}
+
static GLboolean
get_visual_attribs(Display *dpy, XVisualInfo *vInfo,
struct visual_attribs *attribs)
attribs->visualCaveat = 0;
#endif
+#if defined(GLX_EXT_framebuffer_sRGB)
+ if (ext && strstr(ext, "GLX_EXT_framebuffer_sRGB")) {
+ glXGetConfig(dpy, vInfo, GLX_FRAMEBUFFER_SRGB_CAPABLE_EXT, &attribs->srgb);
+ }
+#endif
+
return GL_TRUE;
}
get_fbconfig_attribs(Display *dpy, GLXFBConfig fbconfig,
struct visual_attribs *attribs)
{
+ const char *ext = glXQueryExtensionsString(dpy, 0);
int visual_type;
XVisualInfo *vInfo;
glXGetFBConfigAttrib(dpy, fbconfig, GLX_SAMPLES, &attribs->numSamples);
glXGetFBConfigAttrib(dpy, fbconfig, GLX_CONFIG_CAVEAT, &attribs->visualCaveat);
+#if defined(GLX_NV_float_buffer)
+ if (ext && strstr(ext, "GLX_NV_float_buffer")) {
+ glXGetFBConfigAttrib(dpy, fbconfig, GLX_FLOAT_COMPONENTS_NV, &attribs->floatComponents);
+ }
+#endif
+#if defined(GLX_ARB_fbconfig_float)
+ if (ext && strstr(ext, "GLX_ARB_fbconfig_float")) {
+ if (attribs->render_type & GLX_RGBA_FLOAT_BIT_ARB) {
+ attribs->floatComponents = True;
+ }
+ }
+#endif
+
+#if defined(GLX_EXT_framebuffer_sRGB)
+ if (ext && strstr(ext, "GLX_EXT_framebuffer_sRGB")) {
+ glXGetFBConfigAttrib(dpy, fbconfig, GLX_FRAMEBUFFER_SRGB_CAPABLE_EXT, &attribs->srgb);
+ }
+#endif
return GL_TRUE;
}
attribs->bufferSize, attribs->level,
visual_render_type_name(attribs->render_type),
attribs->doubleBuffer, attribs->stereo);
- printf(" rgba: redSize=%d greenSize=%d blueSize=%d alphaSize=%d\n",
+ printf(" rgba: redSize=%d greenSize=%d blueSize=%d alphaSize=%d float=%c sRGB=%c\n",
attribs->redSize, attribs->greenSize,
- attribs->blueSize, attribs->alphaSize);
+ attribs->blueSize, attribs->alphaSize,
+ attribs->floatComponents ? 'Y' : 'N',
+ attribs->srgb ? 'Y' : 'N');
printf(" auxBuffers=%d depthSize=%d stencilSize=%d\n",
attribs->auxBuffers, attribs->depthSize, attribs->stencilSize);
printf(" accum: redSize=%d greenSize=%d blueSize=%d alphaSize=%d\n",
static void
print_visual_attribs_short_header(void)
{
- printf(" visual x bf lv rg d st colorbuffer ax dp st accumbuffer ms cav\n");
- printf(" id dep cl sp sz l ci b ro r g b a bf th cl r g b a ns b eat\n");
- printf("----------------------------------------------------------------------\n");
+ printf(" visual x bf lv rg d st colorbuffer sr ax dp st accumbuffer ms cav\n");
+ printf(" id dep cl sp sz l ci b ro r g b a F gb bf th cl r g b a ns b eat\n");
+ printf("----------------------------------------------------------------------------\n");
}
static void
print_visual_attribs_short(const struct visual_attribs *attribs)
{
- char *caveat = NULL;
-#ifdef GLX_EXT_visual_rating
- if (attribs->visualCaveat == GLX_NONE_EXT || attribs->visualCaveat == 0)
- caveat = "None";
- else if (attribs->visualCaveat == GLX_SLOW_VISUAL_EXT)
- caveat = "Slow";
- else if (attribs->visualCaveat == GLX_NON_CONFORMANT_VISUAL_EXT)
- caveat = "Ncon";
- else
- caveat = "None";
-#else
- caveat = "None";
-#endif
+ const char *caveat = caveat_string(attribs->visualCaveat);
- printf("0x%02x %2d %2s %2d %2d %2d %c%c %c %c %2d %2d %2d %2d %2d %2d %2d",
+ printf("0x%03x %2d %2s %2d %3d %2d %c%c %c %c %2d %2d %2d %2d %c %c %2d %2d %2d",
attribs->id,
attribs->depth,
visual_class_abbrev(attribs->klass),
attribs->stereo ? 'y' : '.',
attribs->redSize, attribs->greenSize,
attribs->blueSize, attribs->alphaSize,
+ attribs->floatComponents ? 'f' : '.',
+ attribs->srgb ? 's' : '.',
attribs->auxBuffers,
attribs->depthSize,
attribs->stencilSize
static void
print_visual_attribs_long_header(void)
{
- printf("Vis Vis Visual Trans buff lev render DB ste r g b a aux dep ste accum buffers MS MS\n");
- printf(" ID Depth Type parent size el type reo sz sz sz sz buf th ncl r g b a num bufs\n");
- printf("----------------------------------------------------------------------------------------------------\n");
+ printf("Vis Vis Visual Trans buff lev render DB ste r g b a s aux dep ste accum buffer MS MS \n");
+ printf(" ID Depth Type parent size el type reo sz sz sz sz flt rgb buf th ncl r g b a num bufs caveats\n");
+ printf("--------------------------------------------------------------------------------------------------------------------\n");
}
static void
print_visual_attribs_long(const struct visual_attribs *attribs)
{
- printf("0x%2x %2d %-11s %2d %2d %2d %4s %3d %3d %3d %3d %3d %3d",
+ const char *caveat = caveat_string(attribs->visualCaveat);
+
+ printf("0x%3x %2d %-11s %2d %3d %2d %4s %3d %3d %3d %3d %3d %3d",
attribs->id,
attribs->depth,
visual_class_name(attribs->klass),
attribs->blueSize, attribs->alphaSize
);
- printf(" %3d %4d %2d %3d %3d %3d %3d %2d %2d\n",
+ printf(" %c %c %3d %4d %2d %3d %3d %3d %3d %2d %2d %6s\n",
+ attribs->floatComponents ? 'f' : '.',
+ attribs->srgb ? 's' : '.',
attribs->auxBuffers,
attribs->depthSize,
attribs->stencilSize,
attribs->accumRedSize, attribs->accumGreenSize,
attribs->accumBlueSize, attribs->accumAlphaSize,
- attribs->numSamples, attribs->numMultisample
+ attribs->numSamples, attribs->numMultisample,
+ caveat
);
}
@$(MKLIB) -o $(EGL_DRIVER) -noprefix \
-linker '$(CC)' -ldflags '$(LDFLAGS)' \
-L$(TOP)/$(LIB_DIR) $(MKLIB_OPTIONS) \
- $(EGL_OBJECTS) $(EGL_LIBS)
+ $(EGL_OBJECTS) $(EGL_LIBS) -l$(EGL_LIB)
.c.o:
$(CC) -c $(EGL_INCLUDES) $(CFLAGS) $(EGL_CFLAGS) $< -o $@
0, /* __DRI_ATTRIB_BIND_TO_TEXTURE_RGBA */
0, /* __DRI_ATTRIB_BIND_TO_MIPMAP_TEXTURE */
0, /* __DRI_ATTRIB_BIND_TO_TEXTURE_TARGETS */
- 0, /* __DRI_ATTRIB_YINVERTED */
+ EGL_Y_INVERTED_NOK, /* __DRI_ATTRIB_YINVERTED */
};
static void
return dri2_surf->buffers;
}
-#ifdef GLX_USE_TLS
-static const char dri_driver_format[] = "%.*s/tls/%s_dri.so";
-#else
-static const char dri_driver_format[] = "%.*s/%s_dri.so";
-#endif
-
static const char dri_driver_path[] = DEFAULT_DRIVER_DIR;
struct dri2_extension_match {
dri2_dpy->driver = NULL;
end = search_paths + strlen(search_paths);
for (p = search_paths; p < end && dri2_dpy->driver == NULL; p = next + 1) {
+ int len;
next = strchr(p, ':');
if (next == NULL)
next = end;
+ len = next - p;
+#if GLX_USE_TLS
snprintf(path, sizeof path,
- dri_driver_format, (int) (next - p), p, dri2_dpy->driver_name);
+ "%.*s/tls/%s_dri.so", len, p, dri2_dpy->driver_name);
dri2_dpy->driver = dlopen(path, RTLD_NOW | RTLD_GLOBAL);
- if (dri2_dpy->driver == NULL)
- _eglLog(_EGL_DEBUG, "failed to open %s: %s\n", path, dlerror());
+#endif
+ if (dri2_dpy->driver == NULL) {
+ snprintf(path, sizeof path,
+ "%.*s/%s_dri.so", len, p, dri2_dpy->driver_name);
+ dri2_dpy->driver = dlopen(path, RTLD_NOW | RTLD_GLOBAL);
+ if (dri2_dpy->driver == NULL)
+ _eglLog(_EGL_DEBUG, "failed to open %s: %s\n", path, dlerror());
+ }
}
if (dri2_dpy->driver == NULL) {
disp->Extensions.KHR_gl_renderbuffer_image = EGL_TRUE;
disp->Extensions.KHR_gl_texture_2D_image = EGL_TRUE;
disp->Extensions.NOK_swap_region = EGL_TRUE;
+ disp->Extensions.NOK_texture_from_pixmap = EGL_TRUE;
/* we're supporting EGL 1.4 */
*major = 1;
ctx = _eglGetCurrentContext();
dri2_ctx = dri2_egl_context(ctx);
- if (buffer != EGL_BACK_BUFFER) {
- _eglError(EGL_BAD_PARAMETER, "eglBindTexImage");
+ if (!_eglBindTexImage(drv, disp, surf, buffer))
return EGL_FALSE;
- }
-
- /* We allow binding pixmaps too... Not conformat, but we can do it
- * for free and it's useful for X compositors. Supposedly there's
- * a EGL_NOKIA_texture_from_pixmap extension that allows that, but
- * I couldn't find it at this time. */
- if ((dri2_surf->base.Type & (EGL_PBUFFER_BIT | EGL_PIXMAP_BIT)) == 0) {
- _eglError(EGL_BAD_SURFACE, "eglBindTexImage");
- return EGL_FALSE;
- }
switch (dri2_surf->base.TextureFormat) {
case EGL_TEXTURE_RGB:
format = __DRI_TEXTURE_FORMAT_RGBA;
break;
default:
- _eglError(EGL_BAD_MATCH, "eglBindTexImage");
- return EGL_FALSE;
+ assert(0);
}
switch (dri2_surf->base.TextureTarget) {
target = GL_TEXTURE_2D;
break;
default:
- _eglError(EGL_BAD_PARAMETER, "eglBindTexImage");
- return EGL_FALSE;
+ assert(0);
}
(*dri2_dpy->tex_buffer->setTexBuffer2)(dri2_ctx->dri_context,
target, format,
dri2_surf->dri_drawable);
- return dri2_surf->base.BoundToTexture = EGL_TRUE;
+ return EGL_TRUE;
}
static EGLBoolean
#include "eglconfigutil.h"
#include "eglconfig.h"
#include "eglcontext.h"
+#include "egldefines.h"
#include "egldisplay.h"
#include "egldriver.h"
#include "eglcurrent.h"
#include "eglsurface.h"
#define CALLOC_STRUCT(T) (struct T *) calloc(1, sizeof(struct T))
-#define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0]))
#ifndef GLX_VERSION_1_4
#error "GL/glx.h must be equal to or greater than GLX 1.4"
eglInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor)
{
_EGLDisplay *disp = _eglLockDisplay(dpy);
- EGLint major_int, minor_int;
+ EGLint major_int = 0, minor_int = 0;
if (!disp)
RETURN_EGL_ERROR(NULL, EGL_BAD_DISPLAY, EGL_FALSE);
0 },
{ EGL_NONE, ATTRIB_TYPE_PSEUDO,
ATTRIB_CRITERION_IGNORE,
- 0 }
+ 0 },
+
+ { EGL_Y_INVERTED_NOK, ATTRIB_TYPE_BOOLEAN,
+ ATTRIB_CRITERION_EXACT,
+ EGL_DONT_CARE },
+
};
return matched;
}
+static INLINE EGLBoolean
+_eglIsConfigAttribValid(_EGLConfig *conf, EGLint attr)
+{
+ if (_eglIndexConfig(conf, attr) < 0)
+ return EGL_FALSE;
+
+ /* there are some holes in the range */
+ switch (attr) {
+ case 0x3030 /* a gap before EGL_SAMPLES */:
+ case EGL_NONE:
+#ifdef EGL_VERSION_1_4
+ case EGL_MATCH_NATIVE_PIXMAP:
+#endif
+ return EGL_FALSE;
+ case EGL_Y_INVERTED_NOK:
+ return conf->Display->Extensions.NOK_texture_from_pixmap;
+ default:
+ break;
+ }
+
+ return EGL_TRUE;
+}
/**
* Initialize a criteria config from the given attribute list.
/* parse the list */
for (i = 0; attrib_list && attrib_list[i] != EGL_NONE; i += 2) {
- EGLint idx;
-
attr = attrib_list[i];
val = attrib_list[i + 1];
- idx = _eglIndexConfig(conf, attr);
- if (idx < 0)
- return EGL_FALSE;
- conf->Storage[idx] = val;
+ if (!_eglIsConfigAttribValid(conf, attr))
+ return EGL_FALSE;
+
+ SET_CONFIG_ATTRIB(conf, attr, val);
/* rememeber some attributes for post-processing */
switch (attr) {
}
-static INLINE EGLBoolean
-_eglIsConfigAttribValid(_EGLConfig *conf, EGLint attr)
-{
- if (_eglIndexConfig(conf, attr) < 0)
- return EGL_FALSE;
-
- /* there are some holes in the range */
- switch (attr) {
- case 0x3030 /* a gap before EGL_SAMPLES */:
- case EGL_NONE:
-#ifdef EGL_VERSION_1_4
- case EGL_MATCH_NATIVE_PIXMAP:
-#endif
- return EGL_FALSE;
- default:
- break;
- }
-
- return EGL_TRUE;
-}
-
-
/**
* Fallback for eglGetConfigAttrib.
*/
#define _EGL_CONFIG_FIRST_ATTRIB EGL_BUFFER_SIZE
#define _EGL_CONFIG_LAST_ATTRIB EGL_CONFORMANT
-#define _EGL_CONFIG_NUM_ATTRIBS \
+#define _EGL_CONFIG_NUM_CONTIGUOUS_ATTRIBS \
(_EGL_CONFIG_LAST_ATTRIB - _EGL_CONFIG_FIRST_ATTRIB + 1)
-#define _EGL_CONFIG_STORAGE_SIZE _EGL_CONFIG_NUM_ATTRIBS
+/* Attributes outside the contiguous block:
+ *
+ * EGL_Y_INVERTED_NOK
+ */
+#define _EGL_CONFIG_FIRST_EXTRA_ATTRIB _EGL_CONFIG_NUM_CONTIGUOUS_ATTRIBS
+#define _EGL_CONFIG_NUM_EXTRA_ATTRIBS 1
+
+#define _EGL_CONFIG_NUM_ATTRIBS \
+ _EGL_CONFIG_NUM_CONTIGUOUS_ATTRIBS + _EGL_CONFIG_NUM_EXTRA_ATTRIBS
struct _egl_config
{
_EGLDisplay *Display;
- EGLint Storage[_EGL_CONFIG_STORAGE_SIZE];
+ EGLint Storage[_EGL_CONFIG_NUM_ATTRIBS];
};
{
(void) conf;
if (key >= _EGL_CONFIG_FIRST_ATTRIB &&
- key < _EGL_CONFIG_FIRST_ATTRIB + _EGL_CONFIG_NUM_ATTRIBS)
+ key < _EGL_CONFIG_FIRST_ATTRIB + _EGL_CONFIG_NUM_CONTIGUOUS_ATTRIBS)
return key - _EGL_CONFIG_FIRST_ATTRIB;
- else
+
+ switch (key) {
+ case EGL_Y_INVERTED_NOK:
+ return _EGL_CONFIG_FIRST_EXTRA_ATTRIB;
+ default:
return -1;
+ }
}
EGLBoolean KHR_gl_texture_3D_image;
EGLBoolean KHR_gl_renderbuffer_image;
EGLBoolean NOK_swap_region;
+ EGLBoolean NOK_texture_from_pixmap;
char String[_EGL_MAX_EXTENSIONS_LEN];
};
_EGL_CHECK_EXTENSION(KHR_gl_renderbuffer_image);
_EGL_CHECK_EXTENSION(NOK_swap_region);
+ _EGL_CHECK_EXTENSION(NOK_texture_from_pixmap);
#undef _EGL_CHECK_EXTENSION
}
static EGLint
_eglParseSurfaceAttribList(_EGLSurface *surf, const EGLint *attrib_list)
{
+ _EGLDisplay *dpy = surf->Resource.Display;
EGLint type = surf->Type;
+ EGLint texture_type = EGL_PBUFFER_BIT;
EGLint i, err = EGL_SUCCESS;
if (!attrib_list)
return EGL_SUCCESS;
+ if (dpy->Extensions.NOK_texture_from_pixmap)
+ texture_type |= EGL_PIXMAP_BIT;
+
for (i = 0; attrib_list[i] != EGL_NONE; i++) {
EGLint attr = attrib_list[i++];
EGLint val = attrib_list[i];
surf->LargestPbuffer = !!val;
break;
case EGL_TEXTURE_FORMAT:
- if (type != EGL_PBUFFER_BIT) {
+ if (!(type & texture_type)) {
err = EGL_BAD_ATTRIBUTE;
break;
}
surf->TextureFormat = val;
break;
case EGL_TEXTURE_TARGET:
- if (type != EGL_PBUFFER_BIT) {
+ if (!(type & texture_type)) {
err = EGL_BAD_ATTRIBUTE;
break;
}
surf->TextureTarget = val;
break;
case EGL_MIPMAP_TEXTURE:
- if (type != EGL_PBUFFER_BIT) {
+ if (!(type & texture_type)) {
err = EGL_BAD_ATTRIBUTE;
break;
}
_eglBindTexImage(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surface,
EGLint buffer)
{
+ EGLint texture_type = EGL_PBUFFER_BIT;
+
/* Just do basic error checking and return success/fail.
* Drivers must implement the real stuff.
*/
- if (surface->Type != EGL_PBUFFER_BIT) {
+ if (dpy->Extensions.NOK_texture_from_pixmap)
+ texture_type |= EGL_PIXMAP_BIT;
+
+ if (!(surface->Type & texture_type)) {
_eglError(EGL_BAD_SURFACE, "eglBindTexImage");
return EGL_FALSE;
}
return EGL_FALSE;
}
+ if (surface->TextureTarget == EGL_NO_TEXTURE) {
+ _eglError(EGL_BAD_MATCH, "eglBindTexImage");
+ return EGL_FALSE;
+ }
+
if (buffer != EGL_BACK_BUFFER) {
_eglError(EGL_BAD_PARAMETER, "eglBindTexImage");
return EGL_FALSE;
_eglSurfaceAttrib(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf, EGLint attribute, EGLint value);
-extern EGLBoolean
+PUBLIC extern EGLBoolean
_eglBindTexImage(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf, EGLint buffer);
if platform != 'embedded':
SConscript('tests/unit/SConscript')
- SConscript('tests/graw/SConscript')
+ #SConscript('tests/graw/SConscript')
#include "gallivm/lp_bld_printf.h"
#include "tgsi/tgsi_exec.h"
+#include "tgsi/tgsi_dump.h"
#include "util/u_cpu_detect.h"
#include "util/u_string.h"
llvm->pass = LLVMCreateFunctionPassManager(llvm->provider);
LLVMAddTargetData(llvm->target, llvm->pass);
- /* These are the passes currently listed in llvm-c/Transforms/Scalar.h,
- * but there are more on SVN. */
- /* TODO: Add more passes */
- LLVMAddCFGSimplificationPass(llvm->pass);
- LLVMAddPromoteMemoryToRegisterPass(llvm->pass);
- LLVMAddConstantPropagationPass(llvm->pass);
- if(util_cpu_caps.has_sse4_1) {
- /* FIXME: There is a bug in this pass, whereby the combination of fptosi
- * and sitofp (necessary for trunc/floor/ceil/round implementation)
- * somehow becomes invalid code.
+
+ if ((gallivm_debug & GALLIVM_DEBUG_NO_OPT) == 0) {
+ /* These are the passes currently listed in llvm-c/Transforms/Scalar.h,
+ * but there are more on SVN. */
+ /* TODO: Add more passes */
+ LLVMAddCFGSimplificationPass(llvm->pass);
+ LLVMAddPromoteMemoryToRegisterPass(llvm->pass);
+ LLVMAddConstantPropagationPass(llvm->pass);
+ if(util_cpu_caps.has_sse4_1) {
+ /* FIXME: There is a bug in this pass, whereby the combination of fptosi
+ * and sitofp (necessary for trunc/floor/ceil/round implementation)
+ * somehow becomes invalid code.
+ */
+ LLVMAddInstructionCombiningPass(llvm->pass);
+ }
+ LLVMAddGVNPass(llvm->pass);
+ } else {
+ /* We need at least this pass to prevent the backends to fail in
+ * unexpected ways.
*/
- LLVMAddInstructionCombiningPass(llvm->pass);
+ LLVMAddPromoteMemoryToRegisterPass(llvm->pass);
}
- LLVMAddGVNPass(llvm->pass);
init_globals(llvm);
-
-#if 0
- LLVMDumpModule(lp_build_module);
-#endif
+ if (gallivm_debug & GALLIVM_DEBUG_IR) {
+ LLVMDumpModule(llvm->module);
+ }
return llvm;
}
num_vs = 4; /* number of vertices per block */
#endif
- /*tgsi_dump(tokens, 0);*/
+ if (gallivm_debug & GALLIVM_DEBUG_IR) {
+ tgsi_dump(tokens, 0);
+ }
+
lp_build_tgsi_soa(builder,
tokens,
vs_type,
LLVMRunFunctionPassManager(llvm->pass, variant->function);
- if (0) {
+ if (gallivm_debug & GALLIVM_DEBUG_IR) {
lp_debug_dump_value(variant->function);
debug_printf("\n");
}
code = LLVMGetPointerToGlobal(llvm->draw->engine, variant->function);
variant->jit_func = voidptr_to_draw_jit_vert_func(code);
- if (0)
+ if (gallivm_debug & GALLIVM_DEBUG_ASM) {
lp_disassemble(code);
+ }
}
LLVMRunFunctionPassManager(llvm->pass, variant->function_elts);
- if (0) {
+ if (gallivm_debug & GALLIVM_DEBUG_IR) {
lp_debug_dump_value(variant->function_elts);
debug_printf("\n");
}
code = LLVMGetPointerToGlobal(llvm->draw->engine, variant->function_elts);
variant->jit_func_elts = voidptr_to_draw_vert_func_elts(code);
- if (0)
+ if (gallivm_debug & GALLIVM_DEBUG_ASM) {
lp_disassemble(code);
+ }
}
void
#include "util/u_string.h"
+#define GALLIVM_DEBUG_TGSI 0x1
+#define GALLIVM_DEBUG_IR 0x2
+#define GALLIVM_DEBUG_ASM 0x4
+#define GALLIVM_DEBUG_NO_OPT 0x8
+
+
+#ifdef DEBUG
+extern unsigned gallivm_debug;
+#else
+#define gallivm_debug 0
+#endif
+
+
static INLINE void
lp_build_name(LLVMValueRef val, const char *format, ...)
{
* first block may prevent the X86 backend from successfully align the stack as
* required.
*
- * Also the scalarrepl pass is supossedly more powerful and can promote
+ * Also the scalarrepl pass is supposedly more powerful and can promote
* arrays in many cases.
*
* See also:
* It requires that a packed pixel fits into an element of the output
* channels. The common case is when converting pixel with a depth of 32 bit or
* less into floats.
+ *
+ * \param format_desc the format of the 'packed' incoming pixel vector
+ * \param type the desired type for rgba_out (type.length = n, above)
+ * \param packed the incoming vector of packed pixels
+ * \param rgba_out returns the SoA R,G,B,A vectors
*/
void
lp_build_unpack_rgba_soa(LLVMBuilderRef builder,
/* Decode the input vector components */
start = 0;
for (chan = 0; chan < format_desc->nr_channels; ++chan) {
- unsigned width = format_desc->channel[chan].size;
- unsigned stop = start + width;
+ const unsigned width = format_desc->channel[chan].size;
+ const unsigned stop = start + width;
LLVMValueRef input;
input = packed;
/**
- * Fetch a pixel into a SoA.
+ * Fetch a texels from a texture, returning them in SoA layout.
*
- * \param type the desired return type for 'rgba'
+ * \param type the desired return type for 'rgba'. The vector length
+ * is the number of texels to fetch
*
* \param base_ptr points to start of the texture image block. For non-
* compressed formats, this simply points to the texel.
/*
* gather the texels from the texture
+ * Ex: packed = {BGRA, BGRA, BGRA, BGRA}.
*/
packed = lp_build_gather(builder,
type.length,
#include "pipe/p_compiler.h"
#include "util/u_cpu_detect.h"
#include "util/u_debug.h"
+#include "lp_bld_debug.h"
#include "lp_bld_init.h"
+#ifdef DEBUG
+unsigned gallivm_debug = 0;
+
+static const struct debug_named_value lp_bld_debug_flags[] = {
+ { "tgsi", GALLIVM_DEBUG_TGSI },
+ { "ir", GALLIVM_DEBUG_IR },
+ { "asm", GALLIVM_DEBUG_ASM },
+ { "nopt", GALLIVM_DEBUG_NO_OPT },
+ {NULL, 0}
+};
+#endif
+
+
LLVMModuleRef lp_build_module = NULL;
LLVMExecutionEngineRef lp_build_engine = NULL;
LLVMModuleProviderRef lp_build_provider = NULL;
void
lp_build_init(void)
{
+#ifdef DEBUG
+ gallivm_debug = debug_get_flags_option("GALLIVM_DEBUG", lp_bld_debug_flags, 0 );
+#endif
+
LLVMInitializeNativeTarget();
LLVMLinkInJIT();
#define QUAD_BOTTOM_LEFT 2
#define QUAD_BOTTOM_RIGHT 3
+#define LP_MAX_INSTRUCTIONS 256
+
struct lp_exec_mask {
struct lp_build_context *bld;
} loop_stack[LP_MAX_TGSI_NESTING];
int loop_stack_size;
+ LLVMValueRef ret_mask;
+ struct {
+ int pc;
+ LLVMValueRef ret_mask;
+ } call_stack[LP_MAX_TGSI_NESTING];
+ int call_stack_size;
+
LLVMValueRef exec_mask;
};
struct lp_build_mask_context *mask;
struct lp_exec_mask exec_mask;
+
+ struct tgsi_full_instruction *instructions;
+ uint max_instructions;
};
static const unsigned char
mask->has_mask = FALSE;
mask->cond_stack_size = 0;
mask->loop_stack_size = 0;
+ mask->call_stack_size = 0;
mask->int_vec_type = lp_build_int_vec_type(mask->bld->type);
- mask->break_mask = mask->cont_mask = mask->cond_mask =
+ mask->exec_mask = mask->ret_mask = mask->break_mask = mask->cont_mask = mask->cond_mask =
LLVMConstAllOnes(mask->int_vec_type);
}
} else
mask->exec_mask = mask->cond_mask;
+ if (mask->call_stack_size) {
+ mask->exec_mask = LLVMBuildAnd(mask->bld->builder,
+ mask->exec_mask,
+ mask->ret_mask,
+ "callmask");
+ }
mask->has_mask = (mask->cond_stack_size > 0 ||
- mask->loop_stack_size > 0);
+ mask->loop_stack_size > 0 ||
+ mask->call_stack_size > 0);
}
static void lp_exec_mask_cond_push(struct lp_exec_mask *mask,
LLVMBuildStore(mask->bld->builder, val, dst);
}
+static void lp_exec_mask_call(struct lp_exec_mask *mask,
+ int func,
+ int *pc)
+{
+ assert(mask->call_stack_size < LP_MAX_TGSI_NESTING);
+ mask->call_stack[mask->call_stack_size].pc = *pc;
+ mask->call_stack[mask->call_stack_size].ret_mask = mask->ret_mask;
+ mask->call_stack_size++;
+ *pc = func;
+}
+
+static void lp_exec_mask_ret(struct lp_exec_mask *mask, int *pc)
+{
+ LLVMValueRef exec_mask;
+
+ if (mask->call_stack_size == 0) {
+ /* returning from main() */
+ *pc = -1;
+ return;
+ }
+ exec_mask = LLVMBuildNot(mask->bld->builder,
+ mask->exec_mask,
+ "ret");
+
+ mask->ret_mask = LLVMBuildAnd(mask->bld->builder,
+ mask->ret_mask,
+ exec_mask, "ret_full");
+
+ lp_exec_mask_update(mask);
+}
+
+static void lp_exec_mask_bgnsub(struct lp_exec_mask *mask)
+{
+}
+
+static void lp_exec_mask_endsub(struct lp_exec_mask *mask, int *pc)
+{
+ assert(mask->call_stack_size);
+ mask->call_stack_size--;
+ *pc = mask->call_stack[mask->call_stack_size].pc;
+ mask->ret_mask = mask->call_stack[mask->call_stack_size].ret_mask;
+ lp_exec_mask_update(mask);
+}
static LLVMValueRef
emit_ddx(struct lp_build_tgsi_soa_context *bld,
const unsigned chan_index )
{
const struct tgsi_full_src_register *reg = &inst->Src[index];
- unsigned swizzle = tgsi_util_get_full_src_register_swizzle( reg, chan_index );
+ const unsigned swizzle =
+ tgsi_util_get_full_src_register_swizzle(reg, chan_index);
LLVMValueRef res;
LLVMValueRef addr = NULL;
- switch (swizzle) {
- case TGSI_SWIZZLE_X:
- case TGSI_SWIZZLE_Y:
- case TGSI_SWIZZLE_Z:
- case TGSI_SWIZZLE_W:
-
- if (reg->Register.Indirect) {
- LLVMTypeRef int_vec_type = lp_build_int_vec_type(bld->base.type);
- unsigned swizzle = tgsi_util_get_src_register_swizzle( ®->Indirect, chan_index );
- addr = LLVMBuildLoad(bld->base.builder,
- bld->addr[reg->Indirect.Index][swizzle],
- "");
- /* for indexing we want integers */
- addr = LLVMBuildFPToSI(bld->base.builder, addr,
- int_vec_type, "");
- addr = LLVMBuildExtractElement(bld->base.builder,
- addr, LLVMConstInt(LLVMInt32Type(), 0, 0),
- "");
- addr = lp_build_mul(&bld->base, addr, LLVMConstInt(LLVMInt32Type(), 4, 0));
- }
-
- switch (reg->Register.File) {
- case TGSI_FILE_CONSTANT: {
- LLVMValueRef index = LLVMConstInt(LLVMInt32Type(), reg->Register.Index*4 + swizzle, 0);
+ if (swizzle > 3) {
+ assert(0 && "invalid swizzle in emit_fetch()");
+ return bld->base.undef;
+ }
+
+ if (reg->Register.Indirect) {
+ LLVMTypeRef int_vec_type = lp_build_int_vec_type(bld->base.type);
+ unsigned swizzle = tgsi_util_get_src_register_swizzle( ®->Indirect, chan_index );
+ addr = LLVMBuildLoad(bld->base.builder,
+ bld->addr[reg->Indirect.Index][swizzle],
+ "");
+ /* for indexing we want integers */
+ addr = LLVMBuildFPToSI(bld->base.builder, addr,
+ int_vec_type, "");
+ addr = LLVMBuildExtractElement(bld->base.builder,
+ addr, LLVMConstInt(LLVMInt32Type(), 0, 0),
+ "");
+ addr = lp_build_mul(&bld->base, addr, LLVMConstInt(LLVMInt32Type(), 4, 0));
+ }
+
+ switch (reg->Register.File) {
+ case TGSI_FILE_CONSTANT:
+ {
+ LLVMValueRef index = LLVMConstInt(LLVMInt32Type(),
+ reg->Register.Index*4 + swizzle, 0);
LLVMValueRef scalar, scalar_ptr;
if (reg->Register.Indirect) {
"\taddr = %d\n", addr);*/
index = lp_build_add(&bld->base, index, addr);
}
- scalar_ptr = LLVMBuildGEP(bld->base.builder, bld->consts_ptr, &index, 1, "");
+ scalar_ptr = LLVMBuildGEP(bld->base.builder, bld->consts_ptr,
+ &index, 1, "");
scalar = LLVMBuildLoad(bld->base.builder, scalar_ptr, "");
res = lp_build_broadcast_scalar(&bld->base, scalar);
- break;
}
+ break;
- case TGSI_FILE_IMMEDIATE:
- res = bld->immediates[reg->Register.Index][swizzle];
- assert(res);
- break;
+ case TGSI_FILE_IMMEDIATE:
+ res = bld->immediates[reg->Register.Index][swizzle];
+ assert(res);
+ break;
- case TGSI_FILE_INPUT:
- res = bld->inputs[reg->Register.Index][swizzle];
- assert(res);
- break;
+ case TGSI_FILE_INPUT:
+ res = bld->inputs[reg->Register.Index][swizzle];
+ assert(res);
+ break;
- case TGSI_FILE_TEMPORARY: {
+ case TGSI_FILE_TEMPORARY:
+ {
LLVMValueRef temp_ptr = get_temp_ptr(bld, reg->Register.Index,
swizzle,
reg->Register.Indirect,
res = LLVMBuildLoad(bld->base.builder, temp_ptr, "");
if(!res)
return bld->base.undef;
- break;
- }
-
- default:
- assert( 0 );
- return bld->base.undef;
}
break;
default:
- assert( 0 );
+ assert(0 && "invalid src register in emit_fetch()");
return bld->base.undef;
}
case TGSI_FILE_TEMPORARY:
assert(idx < LP_MAX_TGSI_TEMPS);
if (bld->has_indirect_addressing) {
- LLVMValueRef val = LLVMConstInt(LLVMInt32Type(),
- last*4 + 4, 0);
+ LLVMValueRef array_size = LLVMConstInt(LLVMInt32Type(),
+ last*4 + 4, 0);
bld->temps_array = lp_build_array_alloca(bld->base.builder,
- vec_type, val, "");
+ vec_type, array_size, "");
} else {
for (i = 0; i < NUM_CHANNELS; i++)
bld->temps[idx][i] = lp_build_alloca(bld->base.builder,
emit_instruction(
struct lp_build_tgsi_soa_context *bld,
const struct tgsi_full_instruction *inst,
- const struct tgsi_opcode_info *info)
+ const struct tgsi_opcode_info *info,
+ int *pc)
{
unsigned chan_index;
LLVMValueRef src0, src1, src2;
* redundant code.
*/
+ (*pc)++;
+
assert(info->num_dst <= 1);
if (info->num_dst) {
FOR_EACH_DST0_ENABLED_CHANNEL( inst, chan_index ) {
break;
case TGSI_OPCODE_CAL:
- /* FIXME */
- return FALSE;
+ lp_exec_mask_call(&bld->exec_mask,
+ inst->Label.Label,
+ pc);
+
break;
case TGSI_OPCODE_RET:
- /* FIXME */
- return FALSE;
+ lp_exec_mask_ret(&bld->exec_mask, pc);
break;
case TGSI_OPCODE_END:
+ *pc = -1;
break;
case TGSI_OPCODE_SSG:
lp_exec_bgnloop(&bld->exec_mask);
break;
+ case TGSI_OPCODE_BGNSUB:
+ lp_exec_mask_bgnsub(&bld->exec_mask);
+ break;
+
case TGSI_OPCODE_ELSE:
lp_exec_mask_cond_invert(&bld->exec_mask);
break;
lp_exec_endloop(&bld->exec_mask);
break;
+ case TGSI_OPCODE_ENDSUB:
+ lp_exec_mask_endsub(&bld->exec_mask, pc);
+ break;
+
case TGSI_OPCODE_PUSHA:
/* deprecated? */
assert(0);
struct lp_build_tgsi_soa_context bld;
struct tgsi_parse_context parse;
uint num_immediates = 0;
+ uint num_instructions = 0;
unsigned i;
+ int pc = 0;
/* Setup build context */
memset(&bld, 0, sizeof bld);
bld.sampler = sampler;
bld.has_indirect_addressing = info->opcode_count[TGSI_OPCODE_ARR] > 0 ||
info->opcode_count[TGSI_OPCODE_ARL] > 0;
+ bld.instructions = (struct tgsi_full_instruction *)
+ MALLOC( LP_MAX_INSTRUCTIONS * sizeof(struct tgsi_full_instruction) );
+ bld.max_instructions = LP_MAX_INSTRUCTIONS;
+
+ if (!bld.instructions) {
+ return;
+ }
lp_exec_mask_init(&bld.exec_mask, &bld.base);
case TGSI_TOKEN_TYPE_INSTRUCTION:
{
- unsigned opcode = parse.FullToken.FullInstruction.Instruction.Opcode;
- const struct tgsi_opcode_info *opcode_info = tgsi_get_opcode_info(opcode);
- if (!emit_instruction( &bld, &parse.FullToken.FullInstruction, opcode_info ))
- _debug_printf("warning: failed to translate tgsi opcode %s to LLVM\n",
- opcode_info->mnemonic);
+ /* save expanded instruction */
+ if (num_instructions == bld.max_instructions) {
+ bld.instructions = REALLOC(bld.instructions,
+ bld.max_instructions
+ * sizeof(struct tgsi_full_instruction),
+ (bld.max_instructions + LP_MAX_INSTRUCTIONS)
+ * sizeof(struct tgsi_full_instruction));
+ bld.max_instructions += LP_MAX_INSTRUCTIONS;
+ }
+
+ memcpy(bld.instructions + num_instructions,
+ &parse.FullToken.FullInstruction,
+ sizeof(bld.instructions[0]));
+
+ num_instructions++;
}
break;
assert( 0 );
}
}
+
+ while (pc != -1) {
+ struct tgsi_full_instruction *instr = bld.instructions + pc;
+ const struct tgsi_opcode_info *opcode_info =
+ tgsi_get_opcode_info(instr->Instruction.Opcode);
+ if (!emit_instruction( &bld, instr, opcode_info, &pc ))
+ _debug_printf("warning: failed to translate tgsi opcode %s to LLVM\n",
+ opcode_info->mnemonic);
+ }
+
if (0) {
LLVMBasicBlockRef block = LLVMGetInsertBlock(builder);
LLVMValueRef function = LLVMGetBasicBlockParent(block);
debug_printf("2222222222222222222222222222 \n");
}
tgsi_parse_free( &parse );
+
+ if (0) {
+ LLVMModuleRef module = LLVMGetGlobalParent(
+ LLVMGetBasicBlockParent(LLVMGetInsertBlock(bld.base.builder)));
+ LLVMDumpModule(module);
+
+ }
+
+ FREE( bld.instructions );
}
{
struct lp_type res_type;
+ assert(type.length <= LP_MAX_VECTOR_LENGTH);
memset(&res_type, 0, sizeof res_type);
res_type.width = type.width;
res_type.length = type.length;
{
struct lp_type res_type;
+ assert(type.length <= LP_MAX_VECTOR_LENGTH);
memset(&res_type, 0, sizeof res_type);
res_type.width = type.width;
res_type.length = type.length;
}
+/**
+ * Return the size of the LLVMType in bits.
+ * XXX this function doesn't necessarily handle all LLVM types.
+ */
+unsigned
+lp_sizeof_llvm_type(LLVMTypeRef t)
+{
+ LLVMTypeKind k = LLVMGetTypeKind(t);
+
+ switch (k) {
+ case LLVMIntegerTypeKind:
+ return LLVMGetIntTypeWidth(t);
+ case LLVMFloatTypeKind:
+ return 8 * sizeof(float);
+ case LLVMDoubleTypeKind:
+ return 8 * sizeof(double);
+ case LLVMVectorTypeKind:
+ {
+ LLVMTypeRef elem = LLVMGetElementType(t);
+ unsigned len = LLVMGetVectorSize(t);
+ return len * lp_sizeof_llvm_type(elem);
+ }
+ break;
+ case LLVMArrayTypeKind:
+ {
+ LLVMTypeRef elem = LLVMGetElementType(t);
+ unsigned len = LLVMGetArrayLength(t);
+ return len * lp_sizeof_llvm_type(elem);
+ }
+ break;
+ default:
+ assert(0 && "Unexpected type in lp_get_llvm_type_size()");
+ return 0;
+ }
+}
+
+
/**
* Return string name for a LLVMTypeKind. Useful for debugging.
*/
unsigned b = LLVMGetIntTypeWidth(t);
debug_printf("%u-bit Integer\n", b);
}
+ else if (k == LLVMPointerTypeKind) {
+ LLVMTypeRef te = LLVMGetElementType(t);
+ debug_printf("Pointer to ");
+ lp_dump_llvmtype(te);
+ }
else {
debug_printf("%s\n", lp_typekind_name(k));
}
lp_wider_type(struct lp_type type);
+unsigned
+lp_sizeof_llvm_type(LLVMTypeRef t);
+
+
const char *
lp_typekind_name(LLVMTypeKind t);
break;
case TGSI_OPCODE_DIV:
- assert( 0 );
+ exec_vector_binary(mach, inst, micro_div, TGSI_EXEC_DATA_FLOAT, TGSI_EXEC_DATA_FLOAT);
break;
case TGSI_OPCODE_DP2:
return ok;
}
+#else
+
+void ppc_dummy_func(void);
+
+void ppc_dummy_func(void)
+{
+}
+
#endif /* PIPE_ARCH_PPC */
return FALSE;
}
-typedef BOOL (WINAPI *PFNSYMCLEANUP)(HANDLE);
-static PFNSYMCLEANUP pfnSymCleanup = NULL;
-
-static
-BOOL WINAPI j_SymCleanup(HANDLE hProcess)
-{
- if(
- (hModule_Imagehlp || (hModule_Imagehlp = LoadLibraryA("IMAGEHLP.DLL"))) &&
- (pfnSymCleanup || (pfnSymCleanup = (PFNSYMCLEANUP) GetProcAddress(hModule_Imagehlp, "SymCleanup")))
- )
- return pfnSymCleanup(hProcess);
- else
- return FALSE;
-}
-
typedef DWORD (WINAPI *PFNSYMSETOPTIONS)(DWORD);
static PFNSYMSETOPTIONS pfnSymSetOptions = NULL;
return FALSE;
}
-typedef BOOL (WINAPI *PFNSYMUNDNAME)(PIMAGEHLP_SYMBOL, PSTR, DWORD);
-static PFNSYMUNDNAME pfnSymUnDName = NULL;
-
-static
-BOOL WINAPI j_SymUnDName(PIMAGEHLP_SYMBOL Symbol, PSTR UnDecName, DWORD UnDecNameLength)
-{
- if(
- (hModule_Imagehlp || (hModule_Imagehlp = LoadLibraryA("IMAGEHLP.DLL"))) &&
- (pfnSymUnDName || (pfnSymUnDName = (PFNSYMUNDNAME) GetProcAddress(hModule_Imagehlp, "SymUnDName")))
- )
- return pfnSymUnDName(Symbol, UnDecName, UnDecNameLength);
- else
- return FALSE;
-}
-
-typedef PFUNCTION_TABLE_ACCESS_ROUTINE PFNSYMFUNCTIONTABLEACCESS;
-static PFNSYMFUNCTIONTABLEACCESS pfnSymFunctionTableAccess = NULL;
-
-static
-PVOID WINAPI j_SymFunctionTableAccess(HANDLE hProcess, DWORD AddrBase)
-{
- if(
- (hModule_Imagehlp || (hModule_Imagehlp = LoadLibraryA("IMAGEHLP.DLL"))) &&
- (pfnSymFunctionTableAccess || (pfnSymFunctionTableAccess = (PFNSYMFUNCTIONTABLEACCESS) GetProcAddress(hModule_Imagehlp, "SymFunctionTableAccess")))
- )
- return pfnSymFunctionTableAccess(hProcess, AddrBase);
- else
- return NULL;
-}
-
typedef PGET_MODULE_BASE_ROUTINE PFNSYMGETMODULEBASE;
static PFNSYMGETMODULEBASE pfnSymGetModuleBase = NULL;
return 0;
}
-typedef BOOL (WINAPI *PFNSTACKWALK)(DWORD, HANDLE, HANDLE, LPSTACKFRAME, LPVOID, PREAD_PROCESS_MEMORY_ROUTINE, PFUNCTION_TABLE_ACCESS_ROUTINE, PGET_MODULE_BASE_ROUTINE, PTRANSLATE_ADDRESS_ROUTINE);
-static PFNSTACKWALK pfnStackWalk = NULL;
-
-static
-BOOL WINAPI j_StackWalk(
- DWORD MachineType,
- HANDLE hProcess,
- HANDLE hThread,
- LPSTACKFRAME StackFrame,
- PVOID ContextRecord,
- PREAD_PROCESS_MEMORY_ROUTINE ReadMemoryRoutine,
- PFUNCTION_TABLE_ACCESS_ROUTINE FunctionTableAccessRoutine,
- PGET_MODULE_BASE_ROUTINE GetModuleBaseRoutine,
- PTRANSLATE_ADDRESS_ROUTINE TranslateAddress
-)
-{
- if(
- (hModule_Imagehlp || (hModule_Imagehlp = LoadLibraryA("IMAGEHLP.DLL"))) &&
- (pfnStackWalk || (pfnStackWalk = (PFNSTACKWALK) GetProcAddress(hModule_Imagehlp, "StackWalk")))
- )
- return pfnStackWalk(
- MachineType,
- hProcess,
- hThread,
- StackFrame,
- ContextRecord,
- ReadMemoryRoutine,
- FunctionTableAccessRoutine,
- GetModuleBaseRoutine,
- TranslateAddress
- );
- else
- return FALSE;
-}
-
typedef BOOL (WINAPI *PFNSYMGETSYMFROMADDR)(HANDLE, DWORD, LPDWORD, PIMAGEHLP_SYMBOL);
static PFNSYMGETSYMFROMADDR pfnSymGetSymFromAddr = NULL;
return FALSE;
}
-typedef BOOL (WINAPI *PFNSYMGETLINEFROMADDR)(HANDLE, DWORD, LPDWORD, PIMAGEHLP_LINE);
-static PFNSYMGETLINEFROMADDR pfnSymGetLineFromAddr = NULL;
-
-static
-BOOL WINAPI j_SymGetLineFromAddr(HANDLE hProcess, DWORD dwAddr, PDWORD pdwDisplacement, PIMAGEHLP_LINE Line)
-{
- if(
- (hModule_Imagehlp || (hModule_Imagehlp = LoadLibraryA("IMAGEHLP.DLL"))) &&
- (pfnSymGetLineFromAddr || (pfnSymGetLineFromAddr = (PFNSYMGETLINEFROMADDR) GetProcAddress(hModule_Imagehlp, "SymGetLineFromAddr")))
- )
- return pfnSymGetLineFromAddr(hProcess, dwAddr, pdwDisplacement, Line);
- else
- return FALSE;
-}
-
static INLINE boolean
debug_symbol_print_imagehlp(const void *addr)
const char *
util_dump_blend_func(unsigned value, boolean shortened);
+const char *
+util_dump_logicop(unsigned value, boolean shortened);
+
const char *
util_dump_func(unsigned value, boolean shortened);
DEFINE_UTIL_DUMP_CONTINUOUS(blend_func)
+static const char *
+util_dump_logicop_names[] = {
+ "PIPE_LOGICOP_CLEAR",
+ "PIPE_LOGICOP_NOR",
+ "PIPE_LOGICOP_AND_INVERTED",
+ "PIPE_LOGICOP_COPY_INVERTED",
+ "PIPE_LOGICOP_AND_REVERSE",
+ "PIPE_LOGICOP_INVERT",
+ "PIPE_LOGICOP_XOR",
+ "PIPE_LOGICOP_NAND",
+ "PIPE_LOGICOP_AND",
+ "PIPE_LOGICOP_EQUIV",
+ "PIPE_LOGICOP_NOOP",
+ "PIPE_LOGICOP_OR_INVERTED",
+ "PIPE_LOGICOP_COPY",
+ "PIPE_LOGICOP_OR_REVERSE",
+ "PIPE_LOGICOP_OR",
+ "PIPE_LOGICOP_SET"
+};
+
+static const char *
+util_dump_logicop_short_names[] = {
+ "clear",
+ "nor",
+ "and_inverted",
+ "copy_inverted",
+ "and_reverse",
+ "invert",
+ "xor",
+ "nand",
+ "and",
+ "equiv",
+ "noop",
+ "or_inverted",
+ "copy",
+ "or_reverse",
+ "or",
+ "set"
+};
+
+DEFINE_UTIL_DUMP_CONTINUOUS(logicop)
+
+
static const char *
util_dump_func_names[] = {
"PIPE_FUNC_NEVER",
static const char *
util_dump_tex_target_names[] = {
+ "PIPE_BUFFER",
"PIPE_TEXTURE_1D",
"PIPE_TEXTURE_2D",
"PIPE_TEXTURE_3D",
static const char *
util_dump_tex_target_short_names[] = {
+ "buffer",
"1d",
"2d",
"3d",
'''
-import sys
-import math
-
from u_format_parse import *
def is_pot(x):
- return (x & (x - 1)) == 0;
+ return (x & (x - 1)) == 0
VERY_LARGE = 99999999999999999999999
'''
-import sys
import math
# normalize number
while (m & 0x00800000) == 0:
- e -= 0x00800000;
- m <<= 1;
+ e -= 0x00800000
+ m <<= 1
- m &= ~0x00800000;
- e += 0x38800000;
+ m &= ~0x00800000
+ e += 0x38800000
value(m | e)
# normals
will not block and the return value will be TRUE if the query has
completed or FALSE otherwise.
-A common type of query is the occlusion query which counts the number of
-fragments/pixels which are written to the framebuffer (and not culled by
-Z/stencil/alpha testing or shader KILL instructions).
+The most common type of query is the occlusion query,
+``PIPE_QUERY_OCCLUSION_COUNTER``, which counts the number of fragments which
+are written to the framebuffer without being culled by
+:ref:`Depth, Stencil, & Alpha` testing or shader KILL instructions.
+
+Another type of query, ``PIPE_QUERY_TIME_ELAPSED``, returns the amount of
+time, in nanoseconds, the context takes to perform operations.
+
+Gallium does not guarantee the availability of any query types; one must
+always check the capabilities of the :ref:`Screen` first.
Conditional Rendering
The returned map points to the start of the mapped range according to
the box region, not the beginning of the resource.
-.. _transfer_flush_region:
-``transfer_flush_region`` If a transfer was created with TRANFER_FLUSH_EXPLICIT,
-only the region specified is guaranteed to be written to. This is relative to
-the mapped range, not the beginning of the resource.
-
``transfer_unmap`` remove the memory mapping for the transfer object.
Any pointers into the map should be considered invalid and discarded.
Basically get_transfer, transfer_map, data write, transfer_unmap, and
transfer_destroy all in one.
+.. _transfer_flush_region:
+
+transfer_flush_region
+%%%%%%%%%%%%%%%%%%%%%
+
+If a transfer was created with ``FLUSH_EXPLICIT``, it will not automatically
+be flushed on write or unmap. Flushes must be requested with
+``transfer_flush_region``. Flush ranges are relative to the mapped range, not
+the beginning of the resource.
+
.. _pipe_transfer:
PIPE_TRANSFER
operations pending on the resource are undefined. Cannot be used with
``READ``.
* ``FLUSH_EXPLICIT``: Written ranges will be notified later with
- :ref:`transfer_flush_region`. Cannot be used with
- ``READ``.
+ :ref:`transfer_flush_region`. Cannot be used with ``READ``.
+.. _screen:
+
Screen
======
* ``MAX_RENDER_TARGETS``: The maximum number of render targets that may be
bound.
* ``OCCLUSION_QUERY``: Whether occlusion queries are available.
+* ``TIMER_QUERY``: Whether timer queries are available.
* ``TEXTURE_SHADOW_MAP``: XXX
* ``MAX_TEXTURE_2D_LEVELS``: The maximum number of mipmap levels available
for a 2D texture.
return 1;
case PIPE_CAP_OCCLUSION_QUERY:
return 1;
+ case PIPE_CAP_TIMER_QUERY:
+ return 0;
case PIPE_CAP_TEXTURE_SHADOW_MAP:
return 10;
case PIPE_CAP_MAX_TEXTURE_2D_LEVELS:
return 1;
case PIPE_CAP_OCCLUSION_QUERY:
return 0;
+ case PIPE_CAP_TIMER_QUERY:
+ return 0;
case PIPE_CAP_TEXTURE_SHADOW_MAP:
return 1;
case PIPE_CAP_MAX_TEXTURE_2D_LEVELS:
int ret;
if (batch->ptr - batch->map > batch->buf->size) {
- debug_printf("bad relocation ptr %p map %p offset %d size %d\n",
+ debug_printf("bad relocation ptr %p map %p offset %li size %i\n",
batch->ptr, batch->map, batch->ptr - batch->map, batch->buf->size);
return PIPE_ERROR_OUT_OF_MEMORY;
stride = tex->pitch * tex->cpp;
- return bscreen->sws->bo_get_handle(tex->bo, whandle, stride);
+ return bscreen->sws->bo_get_handle(tex->bo, whandle, stride) == PIPE_OK;
}
return 1;
case PIPE_CAP_OCCLUSION_QUERY:
return 0;
+ case PIPE_CAP_TIMER_QUERY:
+ return 0;
case PIPE_CAP_TEXTURE_SHADOW_MAP:
return 1;
case PIPE_CAP_MAX_TEXTURE_2D_LEVELS:
python lp_tile_soa.py ../../auxiliary/util/u_format.csv > $@
LDFLAGS += $(LLVM_LDFLAGS)
-LIBS += $(GL_LIB_DEPS) -L../../auxiliary/ -lgallium libllvmpipe.a $(LLVM_LIBS)
+LIBS += -L../../auxiliary/ -lgallium libllvmpipe.a $(LLVM_LIBS) $(GL_LIB_DEPS)
LD=g++
$(PROGS): lp_test_main.o libllvmpipe.a
#define DEBUG_PIPE 0x1
#define DEBUG_TGSI 0x2
#define DEBUG_TEX 0x4
-#define DEBUG_ASM 0x8
#define DEBUG_SETUP 0x10
#define DEBUG_RAST 0x20
#define DEBUG_QUERY 0x40
#define DEBUG_SCREEN 0x80
-#define DEBUG_JIT 0x100
#define DEBUG_SHOW_TILES 0x200
#define DEBUG_SHOW_SUBTILES 0x400
#define DEBUG_COUNTERS 0x800
-#define DEBUG_NO_LLVM_OPT 0x1000
#ifdef DEBUG
#include "util/u_memory.h"
#include "util/u_cpu_detect.h"
#include "gallivm/lp_bld_init.h"
-#include "lp_debug.h"
+#include "gallivm/lp_bld_debug.h"
#include "lp_screen.h"
#include "gallivm/lp_bld_intr.h"
#include "lp_jit.h"
screen->context_ptr_type = LLVMPointerType(context_type, 0);
}
- if (LP_DEBUG & DEBUG_JIT)
+ if (gallivm_debug & GALLIVM_DEBUG_IR) {
LLVMDumpModule(screen->module);
+ }
}
screen->pass = LLVMCreateFunctionPassManager(screen->provider);
LLVMAddTargetData(screen->target, screen->pass);
- if ((LP_DEBUG & DEBUG_NO_LLVM_OPT) == 0) {
+ if ((gallivm_debug & GALLIVM_DEBUG_NO_OPT) == 0) {
/* These are the passes currently listed in llvm-c/Transforms/Scalar.h,
* but there are more on SVN. */
/* TODO: Add more passes */
{ "pipe", DEBUG_PIPE },
{ "tgsi", DEBUG_TGSI },
{ "tex", DEBUG_TEX },
- { "asm", DEBUG_ASM },
{ "setup", DEBUG_SETUP },
{ "rast", DEBUG_RAST },
{ "query", DEBUG_QUERY },
{ "screen", DEBUG_SCREEN },
- { "jit", DEBUG_JIT },
{ "show_tiles", DEBUG_SHOW_TILES },
{ "show_subtiles", DEBUG_SHOW_SUBTILES },
{ "counters", DEBUG_COUNTERS },
- { "nopt", DEBUG_NO_LLVM_OPT },
{NULL, 0}
};
#endif
return PIPE_MAX_COLOR_BUFS;
case PIPE_CAP_OCCLUSION_QUERY:
return 1;
+ case PIPE_CAP_TIMER_QUERY:
+ return 0;
case PIPE_CAP_TEXTURE_MIRROR_CLAMP:
return 1;
case PIPE_CAP_TEXTURE_MIRROR_REPEAT:
#include "lp_bld_depth.h"
#include "lp_bld_interp.h"
#include "lp_context.h"
-#include "lp_debug.h"
#include "lp_perf.h"
#include "lp_screen.h"
#include "lp_setup.h"
if (1)
LLVMRunFunctionPassManager(screen->pass, function);
- if (LP_DEBUG & DEBUG_JIT) {
+ if (gallivm_debug & GALLIVM_DEBUG_IR) {
/* Print the LLVM IR to stderr */
lp_debug_dump_value(function);
debug_printf("\n");
variant->jit_function[do_tri_test] = cast_voidptr_to_lp_jit_frag_func(f);
- if (LP_DEBUG & DEBUG_ASM)
+ if (gallivm_debug & GALLIVM_DEBUG_ASM) {
lp_disassemble(f);
+ }
}
}
+static void
+dump_fs_variant_key(const struct lp_fragment_shader_variant_key *key)
+{
+ unsigned i;
+
+ debug_printf("fs variant %p:\n", (void *) key);
+
+ if (key->depth.enabled) {
+ debug_printf("depth.format = %s\n", util_format_name(key->zsbuf_format));
+ debug_printf("depth.func = %s\n", util_dump_func(key->depth.func, TRUE));
+ debug_printf("depth.writemask = %u\n", key->depth.writemask);
+ }
+
+ for (i = 0; i < 2; ++i) {
+ if (key->stencil[i].enabled) {
+ debug_printf("stencil[%u].func = %s\n", i, util_dump_func(key->stencil[i].func, TRUE));
+ debug_printf("stencil[%u].fail_op = %s\n", i, util_dump_stencil_op(key->stencil[i].fail_op, TRUE));
+ debug_printf("stencil[%u].zpass_op = %s\n", i, util_dump_stencil_op(key->stencil[i].zpass_op, TRUE));
+ debug_printf("stencil[%u].zfail_op = %s\n", i, util_dump_stencil_op(key->stencil[i].zfail_op, TRUE));
+ debug_printf("stencil[%u].valuemask = 0x%x\n", i, key->stencil[i].valuemask);
+ debug_printf("stencil[%u].writemask = 0x%x\n", i, key->stencil[i].writemask);
+ }
+ }
+
+ if (key->alpha.enabled) {
+ debug_printf("alpha.func = %s\n", util_dump_func(key->alpha.func, TRUE));
+ debug_printf("alpha.ref_value = %f\n", key->alpha.ref_value);
+ }
+
+ if (key->blend.logicop_enable) {
+ debug_printf("blend.logicop_func = %s\n", util_dump_logicop(key->blend.logicop_func, TRUE));
+ }
+ else if (key->blend.rt[0].blend_enable) {
+ debug_printf("blend.rgb_func = %s\n", util_dump_blend_func (key->blend.rt[0].rgb_func, TRUE));
+ debug_printf("blend.rgb_src_factor = %s\n", util_dump_blend_factor(key->blend.rt[0].rgb_src_factor, TRUE));
+ debug_printf("blend.rgb_dst_factor = %s\n", util_dump_blend_factor(key->blend.rt[0].rgb_dst_factor, TRUE));
+ debug_printf("blend.alpha_func = %s\n", util_dump_blend_func (key->blend.rt[0].alpha_func, TRUE));
+ debug_printf("blend.alpha_src_factor = %s\n", util_dump_blend_factor(key->blend.rt[0].alpha_src_factor, TRUE));
+ debug_printf("blend.alpha_dst_factor = %s\n", util_dump_blend_factor(key->blend.rt[0].alpha_dst_factor, TRUE));
+ }
+ debug_printf("blend.colormask = 0x%x\n", key->blend.rt[0].colormask);
+ for (i = 0; i < PIPE_MAX_SAMPLERS; ++i) {
+ if (key->sampler[i].format) {
+ debug_printf("sampler[%u] = \n", i);
+ debug_printf(" .format = %s\n",
+ util_format_name(key->sampler[i].format));
+ debug_printf(" .target = %s\n",
+ util_dump_tex_target(key->sampler[i].target, TRUE));
+ debug_printf(" .pot = %u %u %u\n",
+ key->sampler[i].pot_width,
+ key->sampler[i].pot_height,
+ key->sampler[i].pot_depth);
+ debug_printf(" .wrap = %s %s %s\n",
+ util_dump_tex_wrap(key->sampler[i].wrap_s, TRUE),
+ util_dump_tex_wrap(key->sampler[i].wrap_t, TRUE),
+ util_dump_tex_wrap(key->sampler[i].wrap_r, TRUE));
+ debug_printf(" .min_img_filter = %s\n",
+ util_dump_tex_filter(key->sampler[i].min_img_filter, TRUE));
+ debug_printf(" .min_mip_filter = %s\n",
+ util_dump_tex_mipfilter(key->sampler[i].min_mip_filter, TRUE));
+ debug_printf(" .mag_img_filter = %s\n",
+ util_dump_tex_filter(key->sampler[i].mag_img_filter, TRUE));
+ if (key->sampler[i].compare_mode != PIPE_TEX_COMPARE_NONE)
+ debug_printf(" .compare_func = %s\n", util_dump_func(key->sampler[i].compare_func, TRUE));
+ debug_printf(" .normalized_coords = %u\n", key->sampler[i].normalized_coords);
+ }
+ }
+}
+
+
+
static struct lp_fragment_shader_variant *
generate_variant(struct llvmpipe_context *lp,
struct lp_fragment_shader *shader,
{
struct lp_fragment_shader_variant *variant;
- if (LP_DEBUG & DEBUG_JIT) {
- unsigned i;
-
+ if (gallivm_debug & GALLIVM_DEBUG_IR) {
tgsi_dump(shader->base.tokens, 0);
- if(key->depth.enabled) {
- debug_printf("depth.format = %s\n", util_format_name(key->zsbuf_format));
- debug_printf("depth.func = %s\n", util_dump_func(key->depth.func, TRUE));
- debug_printf("depth.writemask = %u\n", key->depth.writemask);
- }
- for (i = 0; i < 2; ++i) {
- if(key->stencil[i].enabled) {
- debug_printf("stencil[%u].func = %s\n", i, util_dump_func(key->stencil[i].func, TRUE));
- debug_printf("stencil[%u].fail_op = %s\n", i, util_dump_stencil_op(key->stencil[i].fail_op, TRUE));
- debug_printf("stencil[%u].zpass_op = %s\n", i, util_dump_stencil_op(key->stencil[i].zpass_op, TRUE));
- debug_printf("stencil[%u].zfail_op = %s\n", i, util_dump_stencil_op(key->stencil[i].zfail_op, TRUE));
- debug_printf("stencil[%u].valuemask = 0x%x\n", i, key->stencil[i].valuemask);
- debug_printf("stencil[%u].writemask = 0x%x\n", i, key->stencil[i].writemask);
- }
- }
- if(key->alpha.enabled) {
- debug_printf("alpha.func = %s\n", util_dump_func(key->alpha.func, TRUE));
- debug_printf("alpha.ref_value = %f\n", key->alpha.ref_value);
- }
- if(key->blend.logicop_enable) {
- debug_printf("blend.logicop_func = %u\n", key->blend.logicop_func);
- }
- else if(key->blend.rt[0].blend_enable) {
- debug_printf("blend.rgb_func = %s\n", util_dump_blend_func (key->blend.rt[0].rgb_func, TRUE));
- debug_printf("rgb_src_factor = %s\n", util_dump_blend_factor(key->blend.rt[0].rgb_src_factor, TRUE));
- debug_printf("rgb_dst_factor = %s\n", util_dump_blend_factor(key->blend.rt[0].rgb_dst_factor, TRUE));
- debug_printf("alpha_func = %s\n", util_dump_blend_func (key->blend.rt[0].alpha_func, TRUE));
- debug_printf("alpha_src_factor = %s\n", util_dump_blend_factor(key->blend.rt[0].alpha_src_factor, TRUE));
- debug_printf("alpha_dst_factor = %s\n", util_dump_blend_factor(key->blend.rt[0].alpha_dst_factor, TRUE));
- }
- debug_printf("blend.colormask = 0x%x\n", key->blend.rt[0].colormask);
- for(i = 0; i < PIPE_MAX_SAMPLERS; ++i) {
- if(key->sampler[i].format) {
- debug_printf("sampler[%u] = \n", i);
- debug_printf(" .format = %s\n",
- util_format_name(key->sampler[i].format));
- debug_printf(" .target = %s\n",
- util_dump_tex_target(key->sampler[i].target, TRUE));
- debug_printf(" .pot = %u %u %u\n",
- key->sampler[i].pot_width,
- key->sampler[i].pot_height,
- key->sampler[i].pot_depth);
- debug_printf(" .wrap = %s %s %s\n",
- util_dump_tex_wrap(key->sampler[i].wrap_s, TRUE),
- util_dump_tex_wrap(key->sampler[i].wrap_t, TRUE),
- util_dump_tex_wrap(key->sampler[i].wrap_r, TRUE));
- debug_printf(" .min_img_filter = %s\n",
- util_dump_tex_filter(key->sampler[i].min_img_filter, TRUE));
- debug_printf(" .min_mip_filter = %s\n",
- util_dump_tex_mipfilter(key->sampler[i].min_mip_filter, TRUE));
- debug_printf(" .mag_img_filter = %s\n",
- util_dump_tex_filter(key->sampler[i].mag_img_filter, TRUE));
- if(key->sampler[i].compare_mode != PIPE_TEX_COMPARE_NONE)
- debug_printf(" .compare_func = %s\n", util_dump_func(key->sampler[i].compare_func, TRUE));
- debug_printf(" .normalized_coords = %u\n", key->sampler[i].normalized_coords);
- }
- }
+ dump_fs_variant_key(key);
}
variant = CALLOC_STRUCT(lp_fragment_shader_variant);
/* we need to keep a local copy of the tokens */
shader->base.tokens = tgsi_dup_tokens(templ->tokens);
- if (LP_DEBUG & DEBUG_TGSI) {
+ if (gallivm_debug & GALLIVM_DEBUG_TGSI) {
debug_printf("llvmpipe: Create fragment shader %p:\n", (void *) shader);
tgsi_dump(templ->tokens, 0);
}
nv50_program_validate_code(struct nv50_context *nv50, struct nv50_program *p)
{
struct nouveau_channel *chan = nv50->screen->base.channel;
+ struct nouveau_grobj *tesla = nv50->screen->tesla;
struct nv50_program_exec *e;
uint32_t *up, i;
boolean upload = FALSE;
+ unsigned offset;
+ int width;
if (!p->bo) {
nouveau_bo_new(chan->device, NOUVEAU_BO_VRAM, 0x100,
NOUVEAU_ERR("0x%08x\n", e->inst[1]);
}
#endif
- nv50_upload_sifc(nv50, p->bo, 0, NOUVEAU_BO_VRAM,
- NV50_2D_DST_FORMAT_R8_UNORM, 65536, 1, 262144,
- up, NV50_2D_SIFC_FORMAT_R8_UNORM, 0,
- 0, 0, p->exec_size * 4, 1, 1);
+
+ /* SIFC_HEIGHT/SIFC_WIDTH of 65536 do not work, and are not reported
+ * as data error either. hw bug ? */
+#define SIFC_MAX_WIDTH (65536 - 256)
+ offset = 0;
+ width = p->exec_size * 4;
+ while (width > 0) {
+ nv50_upload_sifc(nv50, p->bo, offset, NOUVEAU_BO_VRAM,
+ NV50_2D_DST_FORMAT_R8_UNORM, 65536, 1, 262144,
+ &up[offset / 4], NV50_2D_SIFC_FORMAT_R8_UNORM,
+ 0, 0, 0, MIN2(SIFC_MAX_WIDTH, width), 1, 1);
+ width -= SIFC_MAX_WIDTH;
+ offset += SIFC_MAX_WIDTH;
+ }
+ BEGIN_RING(chan, tesla, NV50TCL_CODE_CB_FLUSH, 1);
+ OUT_RING (chan, 0);
FREE(up);
}
int i;
if (ctx->edgeflag_attr < 16) {
- float *edgeflag = ctx->attr[ctx->edgeflag_attr].map +
+ float *edgeflag = (uint8_t *)ctx->attr[ctx->edgeflag_attr].map +
ctx->attr[ctx->edgeflag_attr].stride * n;
if (*edgeflag != ctx->edgeflag) {
BEGIN_RING_NI(chan, tesla, NV50TCL_VERTEX_DATA, ctx->vtx_size);
for (i = 0; i < ctx->attr_nr; i++)
- ctx->attr[i].push(chan, ctx->attr[i].map + ctx->attr[i].stride * n);
+ ctx->attr[i].push(chan,
+ (uint8_t *)ctx->attr[i].map + ctx->attr[i].stride * n);
}
static void
assert(bo->map);
return;
}
- ctx.attr[n].map = bo->map + vb->buffer_offset + ve->src_offset;
+ ctx.attr[n].map = (uint8_t *)bo->map + vb->buffer_offset + ve->src_offset;
nouveau_bo_unmap(bo);
ctx.attr[n].stride = vb->stride;
ctx.attr[n].divisor = ve->instance_divisor;
if (ctx.attr[n].divisor) {
ctx.attr[n].step = i_start % ve->instance_divisor;
- ctx.attr[n].map += i_start * vb->stride;
+ ctx.attr[n].map = (uint8_t *)ctx.attr[n].map + i_start * vb->stride;
}
size = util_format_get_component_bits(ve->src_format,
ctx.attr[i].divisor != ++ctx.attr[i].step)
continue;
ctx.attr[i].step = 0;
- ctx.attr[i].map += ctx.attr[i].stride;
+ ctx.attr[i].map = (uint8_t *)ctx.attr[i].map + ctx.attr[i].stride;
}
u_split_prim_init(&s, mode, start, count);
return 8;
case PIPE_CAP_OCCLUSION_QUERY:
return 1;
+ case PIPE_CAP_TIMER_QUERY:
+ return 0;
case PIPE_CAP_TEXTURE_SHADOW_MAP:
return 1;
case PIPE_CAP_MAX_TEXTURE_2D_LEVELS:
case PIPE_CAP_TGSI_FS_COORD_ORIGIN_LOWER_LEFT:
case PIPE_CAP_TGSI_FS_COORD_PIXEL_CENTER_INTEGER:
return 0;
+ case PIPE_CAP_MAX_VS_INSTRUCTIONS:
+ case PIPE_CAP_MAX_FS_INSTRUCTIONS:
+ case PIPE_CAP_MAX_VS_ALU_INSTRUCTIONS:
+ case PIPE_CAP_MAX_FS_ALU_INSTRUCTIONS:
+ case PIPE_CAP_MAX_VS_TEX_INSTRUCTIONS:
+ case PIPE_CAP_MAX_FS_TEX_INSTRUCTIONS:
+ case PIPE_CAP_MAX_VS_TEX_INDIRECTIONS:
+ case PIPE_CAP_MAX_FS_TEX_INDIRECTIONS: /* arbitrary limit */
+ return 16384;
+ case PIPE_CAP_MAX_VS_CONTROL_FLOW_DEPTH:
+ case PIPE_CAP_MAX_FS_CONTROL_FLOW_DEPTH: /* need stack bo */
+ return 4;
+ case PIPE_CAP_MAX_VS_INPUTS:
+ return 16;
+ case PIPE_CAP_MAX_FS_INPUTS: /* 128 / 4 with GP */
+ return 64 / 4;
+ case PIPE_CAP_MAX_VS_CONSTS:
+ case PIPE_CAP_MAX_FS_CONSTS:
+ return 65536 / 16;
+ case PIPE_CAP_MAX_VS_ADDRS:
+ case PIPE_CAP_MAX_FS_ADDRS: /* no spilling atm */
+ return 1;
+ case PIPE_CAP_MAX_VS_PREDS:
+ case PIPE_CAP_MAX_FS_PREDS: /* not yet handled */
+ return 0;
+ case PIPE_CAP_MAX_VS_TEMPS:
+ case PIPE_CAP_MAX_FS_TEMPS: /* no spilling atm */
+ return 128 / 4;
default:
NOUVEAU_ERR("Unknown PIPE_CAP %d\n", param);
return 0;
{
struct nouveau_channel *chan = nv50->screen->base.channel;
struct nouveau_grobj *eng2d = nv50->screen->eng2d;
- struct nouveau_grobj *tesla = nv50->screen->tesla;
unsigned line_dwords = (w * cpp + 3) / 4;
reloc |= NOUVEAU_BO_WR;
src = (uint8_t *) src + src_pitch;
}
-
- BEGIN_RING(chan, tesla, NV50TCL_CODE_CB_FLUSH, 1);
- OUT_RING (chan, 0);
}
return screen->is_nv4x ? 4 : 2;
case PIPE_CAP_OCCLUSION_QUERY:
return 1;
+ case PIPE_CAP_TIMER_QUERY:
+ return 0;
case PIPE_CAP_TEXTURE_SHADOW_MAP:
return 1;
case PIPE_CAP_MAX_TEXTURE_2D_LEVELS:
case PIPE_CAP_TGSI_FS_COORD_ORIGIN_UPPER_LEFT:
case PIPE_CAP_TGSI_FS_COORD_PIXEL_CENTER_INTEGER:
return 0;
+ case PIPE_CAP_MAX_FS_INSTRUCTIONS:
+ case PIPE_CAP_MAX_FS_ALU_INSTRUCTIONS:
+ case PIPE_CAP_MAX_FS_TEX_INSTRUCTIONS:
+ case PIPE_CAP_MAX_FS_TEX_INDIRECTIONS:
+ return 4096;
+ case PIPE_CAP_MAX_FS_CONTROL_FLOW_DEPTH:
+ /* FIXME: is it the dynamic (nv30:0/nv40:24) or the static
+ value (written there) ? */
+ return screen->is_nv4x ? 4 : 0;
+ /*case PIPE_CAP_MAX_FS_INPUTS:*/ /* FIXME */
+ /*case PIPE_CAP_MAX_FS_CONSTS:*/ /* FIXME */
+ /* return 0;*/
+ case PIPE_CAP_MAX_FS_TEMPS:
+ return 32;
+ case PIPE_CAP_MAX_FS_ADDRS:
+ return screen->is_nv4x ? 1 : 0;
+ /*case PIPE_CAP_MAX_FS_PREDS:*/ /* FIXME */
+ /* return 0;*/
+ case PIPE_CAP_MAX_VS_INSTRUCTIONS:
+ case PIPE_CAP_MAX_VS_ALU_INSTRUCTIONS:
+ return screen->is_nv4x ? 512 : 256;
+ case PIPE_CAP_MAX_VS_TEX_INSTRUCTIONS:
+ case PIPE_CAP_MAX_VS_TEX_INDIRECTIONS:
+ return screen->is_nv4x ? 512 : 0;
+ case PIPE_CAP_MAX_VS_CONTROL_FLOW_DEPTH:
+ /* FIXME: is it the dynamic (nv30/nv40:24) or the static
+ value (written there) ? */
+ return screen->is_nv4x ? 4 : 1;
+ /*case PIPE_CAP_MAX_VS_INPUTS:*/ /* FIXME */
+ /* return 0;*/
+ case PIPE_CAP_MAX_VS_CONSTS:
+ return 256;
+ case PIPE_CAP_MAX_VS_TEMPS:
+ return screen->is_nv4x ? 48 : 16;
+ case PIPE_CAP_MAX_VS_ADDRS:
+ return 2;
+ /*case PIPE_CAP_MAX_VS_PREDS:*/ /* FIXME */
+ /* return 0;*/
default:
NOUVEAU_ERR("Unknown PIPE_CAP %d\n", param);
return 0;
FREE(r300->ztop_state.state);
FREE(r300->fs_constants.state);
FREE(r300->vs_constants.state);
+ if (!r300->screen->caps.has_tcl) {
+ FREE(r300->vertex_stream_state.state);
+ }
FREE(r300);
}
r300->ztop_state.state = CALLOC_STRUCT(r300_ztop_state);
r300->fs_constants.state = CALLOC_STRUCT(r300_constant_buffer);
r300->vs_constants.state = CALLOC_STRUCT(r300_constant_buffer);
+ if (!r300->screen->caps.has_tcl) {
+ r300->vertex_stream_state.state = CALLOC_STRUCT(r300_vertex_stream_state);
+ }
+
+ /* Some non-CSO atoms don't use the state pointer. */
+ r300->invariant_state.allow_null_state = TRUE;
+ r300->fs_rc_constant_state.allow_null_state = TRUE;
+ r300->pvs_flush.allow_null_state = TRUE;
+ r300->query_start.allow_null_state = TRUE;
+ r300->texture_cache_inval.allow_null_state = TRUE;
}
struct pipe_context* r300_create_context(struct pipe_screen* screen,
draw_set_rasterize_stage(r300->draw, r300_draw_stage(r300));
/* Enable Draw's clipping. */
draw_set_driver_clipping(r300->draw, FALSE);
+ /* Disable converting points/lines to triangles. */
+ draw_wide_line_threshold(r300->draw, 10000000.f);
+ draw_wide_point_threshold(r300->draw, 10000000.f);
}
r300_setup_atoms(r300);
unsigned size;
/* Whether this atom should be emitted. */
boolean dirty;
+ /* Whether this atom may be emitted with state == NULL. */
+ boolean allow_null_state;
};
struct r300_blend_state {
};
struct r300_rs_state {
- /* Draw-specific rasterizer state */
+ /* Original rasterizer state. */
struct pipe_rasterizer_state rs;
+ /* Draw-specific rasterizer state. */
+ struct pipe_rasterizer_state rs_draw;
uint32_t vap_control_status; /* R300_VAP_CNTL_STATUS: 0x2140 */
uint32_t antialiasing_config; /* R300_GB_AA_CONFIG: 0x4020 */
struct r300_query {
/* The kind of query. Currently only OQ is supported. */
unsigned type;
- /* Whether this query is currently active. Only active queries will
- * get emitted into the command stream, and only active queries get
- * tallied. */
- boolean active;
/* The current count of this query. Required to be at least 32 bits. */
unsigned int count;
/* The offset of this query into the query buffer, in bytes. */
enum r300_buffer_tiling microtile, macrotile;
};
-struct r300_vertex_info {
- /* Parent class */
- struct vertex_info vinfo;
-
- /* R300_VAP_PROG_STREAK_CNTL_[0-7] */
- uint32_t vap_prog_stream_cntl[8];
- /* R300_VAP_PROG_STREAK_CNTL_EXT_[0-7] */
- uint32_t vap_prog_stream_cntl_ext[8];
-};
-
struct r300_vertex_element_state {
unsigned count;
struct pipe_vertex_element velem[PIPE_MAX_ATTRIBS];
{ "texalloc", DBG_TEXALLOC, "Texture allocation (for debugging)" },
{ "fall", DBG_FALL, "Fallbacks (for debugging)" },
{ "rs", DBG_RS, "Rasterizer (for debugging)" },
+ { "fb", DBG_FB, "Framebuffer (for debugging)" },
{ "anisohq", DBG_ANISOHQ, "High quality anisotropic filtering (for benchmarking)" },
{ "notiling", DBG_NO_TILING, "Disable tiling (for benchmarking)" },
{ "noimmd", DBG_NO_IMMD, "Disable immediate mode (for benchmarking)" },
}
}
}
+
+void r500_dump_rs_block(struct r300_rs_block *rs)
+{
+ unsigned count, ip, it_count, ic_count, i, j;
+ unsigned tex_ptr;
+ unsigned col_ptr, col_fmt;
+
+ count = rs->inst_count & 0xf;
+ count++;
+
+ it_count = rs->count & 0x7f;
+ ic_count = (rs->count >> 7) & 0xf;
+
+ fprintf(stderr, "RS Block: %d texcoords (linear), %d colors (perspective)\n",
+ it_count, ic_count);
+ fprintf(stderr, "%d instructions\n", count);
+
+ for (i = 0; i < count; i++) {
+ if (rs->inst[i] & 0x10) {
+ ip = rs->inst[i] & 0xf;
+ fprintf(stderr, "texture: ip %d to psf %d\n",
+ ip, (rs->inst[i] >> 5) & 0x7f);
+
+ tex_ptr = rs->ip[ip] & 0xffffff;
+ fprintf(stderr, " : ");
+
+ j = 3;
+ do {
+ if (tex_ptr & 0x3f == 63) {
+ fprintf(stderr, "1.0");
+ } else if (tex_ptr & 0x3f == 62) {
+ fprintf(stderr, "0.0");
+ } else {
+ fprintf(stderr, "[%d]", tex_ptr & 0x3f);
+ }
+ } while (j-- && fprintf(stderr, "/"));
+ fprintf(stderr, "\n");
+ }
+
+ if (rs->inst[i] & 0x10000) {
+ ip = (rs->inst[i] >> 12) & 0xf;
+ fprintf(stderr, "color: ip %d to psf %d\n",
+ ip, (rs->inst[i] >> 18) & 0x7f);
+
+ col_ptr = (rs->ip[ip] >> 24) & 0x7;
+ col_fmt = (rs->ip[ip] >> 27) & 0xf;
+ fprintf(stderr, " : offset %d ", col_ptr);
+
+ switch (col_fmt) {
+ case 0:
+ fprintf(stderr, "(R/G/B/A)");
+ break;
+ case 1:
+ fprintf(stderr, "(R/G/B/0)");
+ break;
+ case 2:
+ fprintf(stderr, "(R/G/B/1)");
+ break;
+ case 4:
+ fprintf(stderr, "(0/0/0/A)");
+ break;
+ case 5:
+ fprintf(stderr, "(0/0/0/0)");
+ break;
+ case 6:
+ fprintf(stderr, "(0/0/0/1)");
+ break;
+ case 8:
+ fprintf(stderr, "(1/1/1/A)");
+ break;
+ case 9:
+ fprintf(stderr, "(1/1/1/0)");
+ break;
+ case 10:
+ fprintf(stderr, "(1/1/1/1)");
+ break;
+ }
+ fprintf(stderr, "\n");
+ }
+ }
+}
}
-static void r300_emit_query_finish(struct r300_context *r300,
- struct r300_query *query)
+static void r300_emit_query_end_frag_pipes(struct r300_context *r300,
+ struct r300_query *query)
{
struct r300_capabilities* caps = &r300->screen->caps;
CS_LOCALS(r300);
END_CS;
}
-static void rv530_emit_query_single(struct r300_context *r300,
- struct r300_query *query)
+static void rv530_emit_query_end_single_z(struct r300_context *r300,
+ struct r300_query *query)
{
CS_LOCALS(r300);
END_CS;
}
-static void rv530_emit_query_double(struct r300_context *r300,
- struct r300_query *query)
+static void rv530_emit_query_end_double_z(struct r300_context *r300,
+ struct r300_query *query)
{
CS_LOCALS(r300);
if (caps->family == CHIP_FAMILY_RV530) {
if (caps->num_z_pipes == 2)
- rv530_emit_query_double(r300, query);
+ rv530_emit_query_end_double_z(r300, query);
else
- rv530_emit_query_single(r300, query);
+ rv530_emit_query_end_single_z(r300, query);
} else
- r300_emit_query_finish(r300, query);
+ r300_emit_query_end_frag_pipes(r300, query);
+
+ query->begin_emitted = FALSE;
}
void r300_emit_rs_state(struct r300_context* r300, unsigned size, void* state)
unsigned count = (rs->inst_count & R300_RS_INST_COUNT_MASK) + 1;
CS_LOCALS(r300);
+ if (SCREEN_DBG_ON(r300->screen, DBG_DRAW)) {
+ r500_dump_rs_block(rs);
+ }
+
DBG(r300, DBG_DRAW, "r300: RS emit:\n");
BEGIN_CS(size);
}
}
/* ...occlusion query buffer... */
- if (r300->query_start.dirty) {
+ if (r300->query_start.dirty ||
+ (r300->query_current && r300->query_current->begin_emitted)) {
if (!r300_add_buffer(r300->rws, r300->oqbo,
0, RADEON_GEM_DOMAIN_GTT)) {
r300->context.flush(&r300->context, 0, NULL);
/*
* Copyright 2008 Corbin Simpson <MostAwesomeDude@gmail.com>
+ * Copyright 2010 Marek Olšák <maraeo@gmail.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
struct r300_context *r300 = r300_context(pipe);
struct r300_query *query;
struct r300_atom *atom;
+ struct pipe_framebuffer_state *fb;
+ unsigned i;
CS_LOCALS(r300);
(void) cs_count;
draw_flush(r300->draw);
}
- r300_emit_query_end(r300);
-
if (r300->dirty_hw) {
+ r300_emit_query_end(r300);
+
FLUSH_CS;
r300->dirty_hw = 0;
/* New kitchen sink, baby. */
foreach(atom, &r300->atom_list) {
- if (atom->state) {
+ if (atom->state || atom->allow_null_state) {
atom->dirty = TRUE;
}
}
foreach(query, &r300->query_list) {
query->flushed = TRUE;
}
+
+ /* XXX
+ *
+ * This is a preliminary implementation of glFinish. Note that st/mesa
+ * uses a non-null fence when glFinish is called and then waits for
+ * the fence. Instead of returning the actual fence, we do the sync
+ * directly.
+ *
+ * The ideal implementation should use something like EmitIrqLocked and
+ * WaitIrq, or better, real fences.
+ *
+ * This feature degrades performance to the level of r300c for games that
+ * use glFinish a lot, even openarena does. Ideally we wouldn't need
+ * glFinish at all if we had proper throttling in swapbuffers so that
+ * the CPU wouldn't outrun the GPU by several frames, so this is basically
+ * a temporary fix for the input lag. Once swap&sync works with DRI2,
+ * I'll be happy to remove this code.
+ *
+ * - M. */
+ if (fence && r300->fb_state.state) {
+ fb = r300->fb_state.state;
+
+ for (i = 0; i < fb->nr_cbufs; i++) {
+ if (fb->cbufs[i]->texture) {
+ r300->rws->buffer_wait(r300->rws,
+ r300_texture(fb->cbufs[i]->texture)->buffer);
+ }
+ if (fb->zsbuf) {
+ r300->rws->buffer_wait(r300->rws,
+ r300_texture(fb->zsbuf->texture)->buffer);
+ }
+ }
+ }
}
void r300_init_flush_functions(struct r300_context* r300)
q->type = query_type;
assert(q->type == PIPE_QUERY_OCCLUSION_COUNTER);
- q->active = FALSE;
-
if (r300screen->caps.family == CHIP_FAMILY_RV530)
query_size = r300screen->caps.num_z_pipes * sizeof(uint32_t);
else
/* XXX */
if (q->offset >= 4096) {
q->offset = 0;
+ fprintf(stderr, "r300: Rewinding OQBO...\n");
}
return (struct pipe_query*)q;
struct r300_context* r300 = r300_context(pipe);
struct r300_query* q = (struct r300_query*)query;
- assert(r300->query_current == NULL);
+ if (r300->query_current != NULL) {
+ fprintf(stderr, "r300: begin_query: "
+ "Some other query has already been started.\n");
+ assert(0);
+ return;
+ }
pipe_buffer_write(pipe,
r300->oqbo,
struct pipe_query* query)
{
struct r300_context* r300 = r300_context(pipe);
- struct r300_query* q = (struct r300_query*)query;
+
+ if ((struct r300_query*)query != r300->query_current) {
+ fprintf(stderr, "r300: end_query: Got invalid query.\n");
+ assert(0);
+ return;
+ }
r300_emit_query_end(r300);
- q->begin_emitted = false;
r300->query_current = NULL;
}
return;
}
+ r300_update_derived_state(r300);
+
for (i = 0; i < r300->vertex_buffer_count; i++) {
void* buf = pipe_buffer_map(pipe,
r300->vertex_buffer[i].buffer,
draw_arrays(r300->draw, mode, start, count);
+ /* XXX Not sure whether this is the best fix.
+ * It prevents CS from being rejected and weird assertion failures. */
+ draw_flush(r300->draw);
+
for (i = 0; i < r300->vertex_buffer_count; i++) {
pipe_buffer_unmap(pipe, r300->vertex_buffer[i].buffer,
vb_transfer[i]);
return;
}
+ r300_update_derived_state(r300);
+
for (i = 0; i < r300->vertex_buffer_count; i++) {
void* buf = pipe_buffer_map(pipe,
r300->vertex_buffer[i].buffer,
draw_arrays(r300->draw, mode, start, count);
+ /* XXX Not sure whether this is the best fix.
+ * It prevents CS from being rejected and weird assertion failures. */
+ draw_flush(r300->draw);
+
for (i = 0; i < r300->vertex_buffer_count; i++) {
pipe_buffer_unmap(pipe, r300->vertex_buffer[i].buffer,
vb_transfer[i]);
size_t vbo_max_used;
void * vbo_ptr;
- struct pipe_transfer *vbo_transfer;
+ struct pipe_transfer *vbo_transfer;
};
static INLINE struct r300_render*
struct r300_render* r300render = r300_render(render);
struct r300_context* r300 = r300render->r300;
- r300_update_derived_state(r300);
-
return &r300->vertex_info;
}
{
struct r300_render* r300render = r300_render(render);
struct pipe_context* context = &r300render->r300->context;
- CS_LOCALS(r300render->r300);
- BEGIN_CS(2);
- OUT_CS_REG(R300_VAP_VF_MAX_VTX_INDX, max);
- END_CS;
r300render->vbo_max_used = MAX2(r300render->vbo_max_used,
r300render->vertex_size * (max + 1));
struct r300_context* r300 = r300render->r300;
uint8_t* ptr;
unsigned i;
+ unsigned dwords = 6;
CS_LOCALS(r300);
- r300_prepare_for_rendering(r300, PREP_FIRST_DRAW, NULL, 2, 0, 0);
+ (void) i; (void) ptr;
+
+ r300_prepare_for_rendering(r300, PREP_FIRST_DRAW, NULL, dwords, 0, 0);
DBG(r300, DBG_DRAW, "r300: Doing vbuf render, count %d\n", count);
r300render->vbo_transfer);
*/
- BEGIN_CS(2);
+ BEGIN_CS(dwords);
+ OUT_CS_REG(R300_GA_COLOR_CONTROL,
+ r300_provoking_vertex_fixes(r300, r300render->prim));
+ OUT_CS_REG(R300_VAP_VF_MAX_VTX_INDX, count - 1);
OUT_CS_PKT3(R300_PACKET3_3D_DRAW_VBUF_2, 0);
OUT_CS(R300_VAP_VF_CNTL__PRIM_WALK_VERTEX_LIST | (count << 16) |
r300render->hwprim);
struct r300_render* r300render = r300_render(render);
struct r300_context* r300 = r300render->r300;
int i;
- unsigned dwords = 2 + (count+1)/2;
+ unsigned dwords = 6 + (count+1)/2;
+ unsigned max_index = (r300render->vbo_size - r300render->vbo_offset) /
+ (r300render->r300->vertex_info.size * 4) - 1;
CS_LOCALS(r300);
r300_prepare_for_rendering(r300, PREP_FIRST_DRAW, NULL, dwords, 0, 0);
BEGIN_CS(dwords);
+ OUT_CS_REG(R300_GA_COLOR_CONTROL,
+ r300_provoking_vertex_fixes(r300, r300render->prim));
+ OUT_CS_REG(R300_VAP_VF_MAX_VTX_INDX, max_index);
OUT_CS_PKT3(R300_PACKET3_3D_DRAW_INDX_2, (count+1)/2);
OUT_CS(R300_VAP_VF_CNTL__PRIM_WALK_INDICES | (count << 16) |
r300render->hwprim);
return 1;
/* Unsupported features (boolean caps). */
+ case PIPE_CAP_TIMER_QUERY:
case PIPE_CAP_DUAL_SOURCE_BLEND:
case PIPE_CAP_TGSI_CONT_SUPPORTED:
case PIPE_CAP_INDEP_BLEND_ENABLE:
* those changes.
*/
/*@{*/
-#define DBG_HELP 0x0000001
-#define DBG_FP 0x0000002
-#define DBG_VP 0x0000004
-#define DBG_CS 0x0000008
-#define DBG_DRAW 0x0000010
-#define DBG_TEX 0x0000020
-#define DBG_FALL 0x0000040
-#define DBG_ANISOHQ 0x0000080
-#define DBG_NO_TILING 0x0000100
-#define DBG_NO_IMMD 0x0000200
-#define DBG_STATS 0x0000400
-#define DBG_RS 0x0000800
-#define DBG_TEXALLOC 0x0001000
+#define DBG_HELP (1 << 0)
+/* Logging. */
+#define DBG_FP (1 << 1)
+#define DBG_VP (1 << 2)
+#define DBG_CS (1 << 3)
+#define DBG_DRAW (1 << 4)
+#define DBG_TEX (1 << 5)
+#define DBG_TEXALLOC (1 << 6)
+#define DBG_RS (1 << 7)
+#define DBG_FALL (1 << 8)
+#define DBG_FB (1 << 9)
+/* Features. */
+#define DBG_ANISOHQ (1 << 16)
+#define DBG_NO_TILING (1 << 17)
+#define DBG_NO_IMMD (1 << 18)
+/* Statistics. */
+#define DBG_STATS (1 << 24)
/*@}*/
static INLINE boolean SCREEN_DBG_ON(struct r300_screen * screen, unsigned flags)
}
}
+static void r300_print_fb_surf_info(struct pipe_surface *surf, unsigned index,
+ const char *binding)
+{
+ struct pipe_resource *tex = surf->texture;
+ struct r300_texture *rtex = r300_texture(tex);
+
+ fprintf(stderr,
+ "r300: %s[%i] Dim: %ix%i, Offset: %i, ZSlice: %i, "
+ "Face: %i, Level: %i, Format: %s\n"
+
+ "r300: TEX: Macro: %s, Micro: %s, Pitch: %i, "
+ "Dim: %ix%ix%i, LastLevel: %i, Format: %s\n",
+
+ binding, index, surf->width, surf->height, surf->offset,
+ surf->zslice, surf->face, surf->level,
+ util_format_short_name(surf->format),
+
+ rtex->macrotile ? "YES" : " NO", rtex->microtile ? "YES" : " NO",
+ rtex->hwpitch[0], tex->width0, tex->height0, tex->depth0,
+ tex->last_level, util_format_short_name(tex->format));
+}
+
static void
r300_set_framebuffer_state(struct pipe_context* pipe,
const struct pipe_framebuffer_state* state)
{
struct r300_context* r300 = r300_context(pipe);
struct pipe_framebuffer_state *old_state = r300->fb_state.state;
- unsigned max_width, max_height;
+ unsigned max_width, max_height, i;
uint32_t zbuffer_bpp = 0;
if (state->nr_cbufs > 4) {
r300->rs_state.dirty = TRUE;
}
}
+
+ if (DBG_ON(r300, DBG_FB)) {
+ fprintf(stderr, "r300: set_framebuffer_state:\n");
+ for (i = 0; i < state->nr_cbufs; i++) {
+ r300_print_fb_surf_info(state->cbufs[i], i, "CB");
+ }
+ if (state->zsbuf) {
+ r300_print_fb_surf_info(state->zsbuf, 0, "ZB");
+ }
+ }
}
/* Create fragment shader state. */
int i;
float psiz;
- /* Copy rasterizer state for Draw. */
+ /* Copy rasterizer state. */
rs->rs = *state;
+ rs->rs_draw = *state;
+
+ /* Override some states for Draw. */
+ rs->rs_draw.sprite_coord_enable = 0; /* We can do this in HW. */
#ifdef PIPE_ARCH_LITTLE_ENDIAN
rs->vap_control_status = R300_VC_NO_SWAP;
int last_sprite_coord_enable = r300->sprite_coord_enable;
boolean last_two_sided_color = r300->two_sided_color;
- if (r300->draw) {
+ if (r300->draw && rs) {
draw_flush(r300->draw);
- draw_set_rasterizer_state(r300->draw, &rs->rs, state);
+ draw_set_rasterizer_state(r300->draw, &rs->rs_draw, state);
}
if (rs) {
}
}
-/* Update the PSC tables. */
+/* Initialize the PSC tables. */
static void r300_vertex_psc(struct r300_vertex_element_state *velems)
{
struct r300_vertex_stream_state *vstream = &velems->vertex_stream;
abort();
}
}
-
}
}
return velems;
if (r300->draw) {
draw_flush(r300->draw);
draw_set_vertex_elements(r300->draw, velems->count, velems->velem);
+ return;
}
UPDATE_STATE(&velems->vertex_stream, r300->vertex_stream_state);
vs->state = *shader;
vs->state.tokens = tgsi_dup_tokens(shader->tokens);
+ r300_init_vs_outputs(vs);
+
if (r300->screen->caps.has_tcl) {
- r300_translate_vertex_shader(r300, vs, vs->state.tokens);
+ r300_translate_vertex_shader(r300, vs);
} else {
vs->draw_vs = draw_create_vertex_shader(r300->draw, shader);
}
struct r300_constant_buffer *cbuf;
struct pipe_transfer *tr;
void *mapped;
- int max_size = 0;
+ int max_size = 0, max_size_bytes = 0, clamped_size = 0;
switch (shader) {
case PIPE_SHADER_VERTEX:
assert(0);
return;
}
+ max_size_bytes = max_size * 4 * sizeof(float);
if (buf == NULL || buf->width0 == 0 ||
(mapped = pipe_buffer_map(pipe, buf, PIPE_TRANSFER_READ, &tr)) == NULL)
return;
}
- assert((buf->width0 % 4 * sizeof(float)) == 0);
+ if (shader == PIPE_SHADER_FRAGMENT ||
+ (shader == PIPE_SHADER_VERTEX && r300->screen->caps.has_tcl)) {
+ assert((buf->width0 % (4 * sizeof(float))) == 0);
- /* Check the size of the constant buffer. */
- /* XXX Subtract immediates and RC_STATE_* variables. */
- if (buf->width0 > (sizeof(float) * 4 * max_size)) {
- fprintf(stderr, "r300: Max size of the constant buffer is "
- "%i*4 floats.\n", max_size);
- abort();
- }
+ /* Check the size of the constant buffer. */
+ /* XXX Subtract immediates and RC_STATE_* variables. */
+ if (buf->width0 > max_size_bytes) {
+ fprintf(stderr, "r300: Max size of the constant buffer is "
+ "%i*4 floats.\n", max_size);
+ }
+ clamped_size = MIN2(buf->width0, max_size_bytes);
- memcpy(cbuf->constants, mapped, buf->width0);
- cbuf->count = buf->width0 / (4 * sizeof(float));
- pipe_buffer_unmap(pipe, buf, tr);
+ memcpy(cbuf->constants, mapped, clamped_size);
+ cbuf->count = clamped_size / (4 * sizeof(float));
+ }
if (shader == PIPE_SHADER_VERTEX) {
if (r300->screen->caps.has_tcl) {
r300->pvs_flush.dirty = TRUE;
} else if (r300->draw) {
draw_set_mapped_constant_buffer(r300->draw, PIPE_SHADER_VERTEX,
- 0, cbuf->constants,
- buf->width0);
+ 0, mapped, buf->width0);
}
} else if (shader == PIPE_SHADER_FRAGMENT) {
r300->fs_constants.dirty = TRUE;
}
+
+ pipe_buffer_unmap(pipe, buf, tr);
}
void r300_init_state_functions(struct r300_context* r300)
static void r300_swtcl_vertex_psc(struct r300_context *r300)
{
struct r300_vertex_stream_state *vstream = r300->vertex_stream_state.state;
- struct vertex_info* vinfo = &r300->vertex_info;
+ struct vertex_info *vinfo = &r300->vertex_info;
uint16_t type, swizzle;
enum pipe_format format;
unsigned i, attrib_count;
int* vs_output_tab = r300->stream_loc_notcl;
- /* XXX hax */
memset(vstream, 0, sizeof(struct r300_vertex_stream_state));
/* For each Draw attribute, route it to the fragment shader according
if (r300->rs_block_state.dirty) {
r300_update_rs_block(r300);
- }
- if (r300->draw) {
- memset(&r300->vertex_info, 0, sizeof(struct vertex_info));
- r300_draw_emit_all_attribs(r300);
- draw_compute_vertex_size(&r300->vertex_info);
- r300_swtcl_vertex_psc(r300);
+ if (r300->draw) {
+ memset(&r300->vertex_info, 0, sizeof(struct vertex_info));
+ r300_draw_emit_all_attribs(r300);
+ draw_compute_vertex_size(&r300->vertex_info);
+ r300_swtcl_vertex_psc(r300);
+ }
}
r300_update_hyperz_state(r300);
state.tokens = ureg_finalize(ureg);
shader->dummy = TRUE;
- r300_translate_vertex_shader(r300, shader, state.tokens);
+ r300_translate_vertex_shader(r300, shader);
ureg_destroy(ureg);
}
-void r300_translate_vertex_shader(struct r300_context* r300,
- struct r300_vertex_shader* vs,
- const struct tgsi_token *tokens)
+void r300_init_vs_outputs(struct r300_vertex_shader *vs)
+{
+ tgsi_scan_shader(vs->state.tokens, &vs->info);
+ r300_shader_read_vs_outputs(&vs->info, &vs->outputs);
+}
+
+void r300_translate_vertex_shader(struct r300_context *r300,
+ struct r300_vertex_shader *vs)
{
struct r300_vertex_program_compiler compiler;
struct tgsi_to_rc ttr;
- tgsi_scan_shader(tokens, &vs->info);
- r300_shader_read_vs_outputs(&vs->info, &vs->outputs);
-
/* Setup the compiler */
rc_init(&compiler.Base);
if (compiler.Base.Debug) {
debug_printf("r300: Initial vertex program\n");
- tgsi_dump(tokens, 0);
+ tgsi_dump(vs->state.tokens, 0);
}
/* Translate TGSI to our internal representation */
ttr.info = &vs->info;
ttr.use_half_swizzles = FALSE;
- r300_tgsi_to_rc(&ttr, tokens);
+ r300_tgsi_to_rc(&ttr, vs->state.tokens);
compiler.RequiredOutputs = ~(~0 << (vs->info.num_outputs + 1));
compiler.SetHwInputOutput = &set_vertex_inputs_outputs;
void *draw_vs;
};
-void r300_translate_vertex_shader(struct r300_context* r300,
- struct r300_vertex_shader* vs,
- const struct tgsi_token *tokens);
+void r300_init_vs_outputs(struct r300_vertex_shader *vs);
+void r300_translate_vertex_shader(struct r300_context *r300,
+ struct r300_vertex_shader *vs);
#endif /* R300_VS_H */
struct r300_winsys_buffer **pdst,
struct r300_winsys_buffer *src);
- boolean (*buffer_references)(struct r300_winsys_buffer *a,
- struct r300_winsys_buffer *b);
-
- void (*buffer_flush_range)(struct r300_winsys_screen *rws,
- struct r300_winsys_buffer *buf,
- unsigned offset,
- unsigned length);
+ void (*buffer_wait)(struct r300_winsys_screen *rws,
+ struct r300_winsys_buffer *buf);
/* Add a pipe_resource to the list of buffer objects to validate. */
boolean (*add_buffer)(struct r300_winsys_screen *winsys,
#include "rbug_context.h"
#include "rbug_objects.h"
-DEBUG_GET_ONCE_BOOL_OPTION(rbug, "GALLIUM_RBUG", FALSE);
+DEBUG_GET_ONCE_BOOL_OPTION(rbug, "GALLIUM_RBUG", FALSE)
static void
rbug_screen_destroy(struct pipe_screen *_screen)
*/
#include "draw/draw_context.h"
+#include "os/os_time.h"
#include "pipe/p_defines.h"
#include "util/u_memory.h"
#include "sp_context.h"
#include "sp_state.h"
struct softpipe_query {
+ unsigned type;
uint64_t start;
uint64_t end;
};
softpipe_create_query(struct pipe_context *pipe,
unsigned type)
{
- assert(type == PIPE_QUERY_OCCLUSION_COUNTER);
- return (struct pipe_query *)CALLOC_STRUCT( softpipe_query );
+ struct softpipe_query* sq;
+
+ assert(type == PIPE_QUERY_OCCLUSION_COUNTER || type == PIPE_QUERY_TIME_ELAPSED);
+ sq = CALLOC_STRUCT( softpipe_query );
+ sq->type = type;
+
+ return (struct pipe_query *)sq;
}
struct softpipe_context *softpipe = softpipe_context( pipe );
struct softpipe_query *sq = softpipe_query(q);
- sq->start = softpipe->occlusion_count;
+ switch (sq->type) {
+ case PIPE_QUERY_OCCLUSION_COUNTER:
+ sq->start = softpipe->occlusion_count;
+ break;
+ case PIPE_QUERY_TIME_ELAPSED:
+ sq->start = 1000*os_time_get();
+ break;
+ default:
+ assert(0);
+ break;
+ }
softpipe->active_query_count++;
softpipe->dirty |= SP_NEW_QUERY;
}
struct softpipe_query *sq = softpipe_query(q);
softpipe->active_query_count--;
- sq->end = softpipe->occlusion_count;
+ switch (sq->type) {
+ case PIPE_QUERY_OCCLUSION_COUNTER:
+ sq->end = softpipe->occlusion_count;
+ break;
+ case PIPE_QUERY_TIME_ELAPSED:
+ sq->end = 1000*os_time_get();
+ break;
+ default:
+ assert(0);
+ break;
+ }
softpipe->dirty |= SP_NEW_QUERY;
}
return PIPE_MAX_COLOR_BUFS;
case PIPE_CAP_OCCLUSION_QUERY:
return 1;
+ case PIPE_CAP_TIMER_QUERY:
+ return 1;
case PIPE_CAP_TEXTURE_MIRROR_CLAMP:
return 1;
case PIPE_CAP_TEXTURE_MIRROR_REPEAT:
if (spt) {
struct pipe_transfer *pt = &spt->base;
enum pipe_format format = resource->format;
+ const unsigned hgt = u_minify(spr->base.height0, sr.level);
+ const unsigned nblocksy = util_format_get_nblocksy(format, hgt);
+
pipe_resource_reference(&pt->resource, resource);
pt->sr = sr;
pt->usage = usage;
pt->box = *box;
pt->stride = spr->stride[sr.level];
+ pt->slice_stride = pt->stride * nblocksy;
spt->offset = sp_get_tex_image_offset(spr, sr.level, sr.face, box->z);
return MIN2(result.u, PIPE_MAX_COLOR_BUFS);
case PIPE_CAP_OCCLUSION_QUERY:
return 1;
+ case PIPE_CAP_TIMER_QUERY:
+ return 0;
case PIPE_CAP_TEXTURE_SHADOW_MAP:
return 1;
struct svga_context;
struct pipe_context;
-struct pipe_buffer;
struct vbuf_render;
#include "pipe/p_compiler.h"
#include "pipe/p_format.h"
-struct pipe_buffer;
struct pipe_resource;
struct pipe_surface;
struct pipe_transfer;
#define PIPE_QUERY_OCCLUSION_COUNTER 0
#define PIPE_QUERY_PRIMITIVES_GENERATED 1
#define PIPE_QUERY_PRIMITIVES_EMITTED 2
-#define PIPE_QUERY_TYPES 3
+#define PIPE_QUERY_TIME_ELAPSED 3
+#define PIPE_QUERY_TYPES 4
/**
PIPE_CAP_POINT_SPRITE,
PIPE_CAP_MAX_RENDER_TARGETS,
PIPE_CAP_OCCLUSION_QUERY,
+ PIPE_CAP_TIMER_QUERY,
PIPE_CAP_TEXTURE_SHADOW_MAP,
PIPE_CAP_MAX_TEXTURE_2D_LEVELS,
PIPE_CAP_MAX_TEXTURE_3D_LEVELS,
/** Opaque type */
struct pipe_fence_handle;
struct pipe_winsys;
-struct pipe_texture;
struct pipe_resource;
struct pipe_surface;
struct pipe_transfer;
struct pipe_screen;
struct pipe_winsys;
-struct pipe_buffer;
struct pipe_context;
struct pipe_resource;
struct pipe_screen;
struct pipe_winsys;
-struct pipe_buffer;
struct pipe_context;
struct pipe_resource;
#include "pipe/p_format.h"
struct pipe_screen;
-
-PUBLIC struct pipe_screen *graw_init( void );
+struct pipe_context;
/* Returns a handle to be used with flush_frontbuffer()/present().
*
* Query format support with screen::is_format_supported and usage
* XXX.
*/
-PUBLIC void *graw_create_window( int x,
- int y,
- unsigned width,
- unsigned height,
- enum pipe_format format );
+PUBLIC struct pipe_screen *graw_create_window_and_screen( int x,
+ int y,
+ unsigned width,
+ unsigned height,
+ enum pipe_format format,
+ void **handle);
+
+PUBLIC void graw_set_display_func( void (*func)( void ) );
+PUBLIC void graw_main_loop( void );
+
+PUBLIC void *graw_parse_vertex_shader( struct pipe_context *pipe,
+ const char *text );
-PUBLIC void graw_destroy_window( void *handle );
+PUBLIC void *graw_parse_fragment_shader( struct pipe_context *pipe,
+ const char *text );
#endif
#include <string.h>
#include "GL/glx.h"
#include "glapi/glapi.h"
-#include "pipe/p_compiler.h"
struct name_address_pair {
xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(crtc->scrn);
modesettingPtr ms = modesettingPTR(crtc->scrn);
xf86OutputPtr output = NULL;
- drmModeConnectorPtr drm_connector;
struct crtc_private *crtcp = crtc->driver_private;
drmModeCrtcPtr drm_crtc = crtcp->drm_crtc;
drmModeModeInfo drm_mode;
- int i, ret;
+ int i, ret, connector_id;
for (i = 0; i < config->num_output; output = NULL, i++) {
output = config->output[i];
if (!output)
return FALSE;
- drm_connector = output->driver_private;
+ connector_id = xorg_output_get_id(output);
drm_mode.clock = mode->Clock;
drm_mode.hdisplay = mode->HDisplay;
drm_mode.name[DRM_DISPLAY_MODE_LEN - 1] = '\0';
ret = drmModeSetCrtc(ms->fd, drm_crtc->crtc_id, ms->fb_id, x, y,
- &drm_connector->connector_id, 1, &drm_mode);
+ &connector_id, 1, &drm_mode);
if (ret)
return FALSE;
}
#endif
- dri2info.version = DRI2INFOREC_VERSION;
+ dri2info.version = min(DRI2INFOREC_VERSION, 3);
dri2info.fd = ms->fd;
dri2info.driverName = pScrn->driverName;
static Bool drv_init_front_buffer_functions(ScrnInfoPtr pScrn);
static Bool drv_close_screen(int scrnIndex, ScreenPtr pScreen);
-static Bool drv_save_hw_state(ScrnInfoPtr pScrn);
-static Bool drv_restore_hw_state(ScrnInfoPtr pScrn);
/*
drv_close_resource_management(ScrnInfoPtr pScrn)
{
modesettingPtr ms = modesettingPTR(pScrn);
- int i;
if (ms->screen) {
assert(ms->ctx == NULL);
-
- for (i = 0; i < XORG_NR_FENCES; i++) {
- if (ms->fence[i]) {
- ms->screen->fence_finish(ms->screen, ms->fence[i], 0);
- ms->screen->fence_reference(ms->screen, &ms->fence[i], NULL);
- }
- }
ms->screen->destroy(ms->screen);
}
ms->screen = NULL;
return TRUE;
}
+static void
+drv_cleanup_fences(ScrnInfoPtr pScrn)
+{
+ modesettingPtr ms = modesettingPTR(pScrn);
+ int i;
+
+ assert(ms->screen);
+
+ for (i = 0; i < XORG_NR_FENCES; i++) {
+ if (ms->fence[i]) {
+ ms->screen->fence_finish(ms->screen, ms->fence[i], 0);
+ ms->screen->fence_reference(ms->screen, &ms->fence[i], NULL);
+ }
+ }
+}
+
static Bool
drv_pre_init(ScrnInfoPtr pScrn, int flags)
{
return FALSE;
ms = modesettingPTR(pScrn);
- ms->SaveGeneration = -1;
ms->pEnt = pEnt;
ms->cust = cust;
ms->SWCursor = TRUE;
}
- drv_save_hw_state(pScrn);
-
xorg_crtc_init(pScrn);
xorg_output_init(pScrn);
if (!xf86InitialConfiguration(pScrn, TRUE)) {
xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No valid modes.\n");
- drv_restore_hw_state(pScrn);
return FALSE;
}
- drv_restore_hw_state(pScrn);
-
/*
* If the driver can do gamma correction, it should call xf86SetGamma() here.
*/
return TRUE;
}
-static Bool
-drv_save_hw_state(ScrnInfoPtr pScrn)
-{
- /*xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);*/
-
- return TRUE;
-}
-
-static Bool
-drv_restore_hw_state(ScrnInfoPtr pScrn)
-{
- /*xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn);*/
-
- return TRUE;
-}
-
static void drv_block_handler(int i, pointer blockData, pointer pTimeout,
pointer pReadmask)
{
drmModeRmFB(ms->fd, ms->fb_id);
ms->fb_id = -1;
- drv_restore_hw_state(pScrn);
+ /* idle hardware */
+ if (!ms->kms)
+ drv_cleanup_fences(pScrn);
if (drmDropMaster(ms->fd))
xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
}
}
- /*
- * Only save state once per server generation since that's what most
- * drivers do. Could change this to save state at each VT enter.
- */
- if (ms->SaveGeneration != serverGeneration) {
- ms->SaveGeneration = serverGeneration;
- drv_save_hw_state(pScrn);
- }
-
if (!ms->create_front_buffer(pScrn))
return FALSE;
modesettingPtr ms = modesettingPTR(pScrn);
CustomizerPtr cust = ms->cust;
- if (pScrn->vtSema) {
- drv_leave_vt(scrnIndex, 0);
- }
-
if (ms->cursor) {
FreeCursor(ms->cursor, None);
ms->cursor = NULL;
xorg_exa_close(pScrn);
ms->exa = NULL;
+ /* calls drop master make sure we don't talk to 3D HW after that */
+ if (pScrn->vtSema) {
+ drv_leave_vt(scrnIndex, 0);
+ }
+
drv_close_resource_management(pScrn);
drv_close_drm(pScrn);
renderer_destroy(exa->renderer);
+ xorg_exa_finish(exa);
+
if (exa->pipe)
exa->pipe->destroy(exa->pipe);
exa->pipe = NULL;
#include "xorg_tracker.h"
+struct output_private
+{
+ drmModeConnectorPtr drm_connector;
+
+ int c;
+};
+
static char *output_enum_list[] = {
"Unknown",
"VGA",
static xf86OutputStatus
output_detect(xf86OutputPtr output)
{
- drmModeConnectorPtr drm_connector = output->driver_private;
+ modesettingPtr ms = modesettingPTR(output->scrn);
+ struct output_private *priv = output->driver_private;
+ drmModeConnectorPtr drm_connector;
+ xf86OutputStatus status;
+
+ drm_connector = drmModeGetConnector(ms->fd, priv->drm_connector->connector_id);
+ if (drm_connector) {
+ drmModeFreeConnector(priv->drm_connector);
+ priv->drm_connector = drm_connector;
+ } else {
+ drm_connector = priv->drm_connector;
+ }
switch (drm_connector->connection) {
case DRM_MODE_CONNECTED:
- return XF86OutputStatusConnected;
+ status = XF86OutputStatusConnected;
+ break;
case DRM_MODE_DISCONNECTED:
- return XF86OutputStatusDisconnected;
+ status = XF86OutputStatusDisconnected;
+ break;
default:
- return XF86OutputStatusUnknown;
+ status = XF86OutputStatusUnknown;
}
+
+ return status;
}
static DisplayModePtr
output_get_modes(xf86OutputPtr output)
{
- drmModeConnectorPtr drm_connector = output->driver_private;
+ struct output_private *priv = output->driver_private;
+ drmModeConnectorPtr drm_connector = priv->drm_connector;
drmModeModeInfoPtr drm_mode = NULL;
DisplayModePtr modes = NULL, mode = NULL;
int i;
static void
output_destroy(xf86OutputPtr output)
{
- drmModeFreeConnector(output->driver_private);
+ struct output_private *priv = output->driver_private;
+ drmModeFreeConnector(priv->drm_connector);
+ xfree(priv);
+ output->driver_private = NULL;
}
static const xf86OutputFuncsRec output_funcs = {
drmModeResPtr res;
drmModeConnectorPtr drm_connector = NULL;
drmModeEncoderPtr drm_encoder = NULL;
+ struct output_private *priv;
char name[32];
int c, v, p;
drm_connector->connector_type_id);
+ priv = xcalloc(sizeof(*priv), 1);
+ if (!priv) {
+ continue;
+ }
+
output = xf86OutputCreate(pScrn, &output_funcs, name);
- if (!output)
+ if (!output) {
+ xfree(priv);
continue;
+ }
drm_encoder = drmModeGetEncoder(ms->fd, drm_connector->encoders[0]);
if (drm_encoder) {
output->possible_crtcs = 0;
output->possible_clones = 0;
}
- output->driver_private = drm_connector;
+ priv->c = c;
+ priv->drm_connector = drm_connector;
+ output->driver_private = priv;
output->subpixel_order = SubPixelHorizontalRGB;
output->interlaceAllowed = FALSE;
output->doubleScanAllowed = FALSE;
drmModeFreeResources(res);
}
+unsigned
+xorg_output_get_id(xf86OutputPtr output)
+{
+ struct output_private *priv = output->driver_private;
+ return priv->drm_connector->connector_id;
+}
+
/* vim: set sw=4 ts=8 sts=4: */
#include "util/u_draw_quad.h"
#include "util/u_math.h"
#include "util/u_memory.h"
-#include "util/u_rect.h"
#include "util/u_sampler.h"
#include "util/u_surface.h"
/* Broken-out options. */
OptionInfoPtr Options;
- unsigned int SaveGeneration;
-
void (*blockHandler)(int, pointer, pointer, pointer);
struct pipe_fence_handle *fence[XORG_NR_FENCES];
void
xorg_output_init(ScrnInfoPtr pScrn);
+unsigned
+xorg_output_get_id(xf86OutputPtr output);
+
/***********************************************************************
* xorg_xv.c
$(MKLIB_OPTIONS) $(EGL_DRIVER_OBJECTS) \
-Wl,--start-group $($(1)_ST) $(EGL_DRIVER_PIPES) \
$(GALLIUM_AUXILIARIES) -Wl,--end-group \
- $($(1)_LIBS) $(EGL_DRIVER_LIBS)
+ $($(1)_LIBS) $(EGL_DRIVER_LIBS) -L$(TOP)/$(LIB_DIR) -l$(EGL_LIB)
endef
egl_x11_$(EGL_DRIVER_NAME).so: $(EGL_DRIVER_OBJECTS) $(x11_ST) $(EGL_DRIVER_PIPES) $(GALLIUM_AUXILIARIES) Makefile
+import os
Import('*')
+# Compatibility with old build scripts:
+#
if 'xlib' in env['winsys']:
SConscript([
'libgl-xlib/SConscript',
'libgl-gdi/SConscript',
])
-if env['platform'] == 'linux' and 'xlib' in env['winsys'] and 'graw-xlib' in env['winsys']:
- SConscript([
- 'graw-xlib/SConscript',
- ])
-else:
- if not env['msvc']:
+if not 'graw-xlib' in env['targets'] and not env['msvc']:
# XXX: disable until MSVC can link correctly
SConscript('graw-null/SConscript')
SConscript([
'xorg-vmwgfx/SConscript',
])
+
+# Ideally all non-target directories would produce convenience
+# libraries, and the actual shared libraries and other installables
+# would be finally assembled in the targets subtree:
+#
+for target in env['targets']:
+ SConscript(os.path.join(target, 'SConscript'))
+
+
+
#include "sw/sw_public.h"
#include "sw/sw.c"
-#include "state_tracker/graw.h"
-
#include <stdio.h>
sources = [
'graw_xlib.c',
+ 'graw_util.c',
]
if True:
--- /dev/null
+
+#include "pipe/p_compiler.h"
+#include "pipe/p_context.h"
+#include "tgsi/tgsi_text.h"
+#include "util/u_memory.h"
+#include "state_tracker/graw.h"
+
+
+/* Helper functions. These are the same for all graw implementations.
+ */
+void *graw_parse_vertex_shader(struct pipe_context *pipe,
+ const char *text)
+{
+ struct tgsi_token tokens[1024];
+ struct pipe_shader_state state;
+
+ if (!tgsi_text_translate(text, tokens, Elements(tokens)))
+ return NULL;
+
+ state.tokens = tokens;
+ return pipe->create_vs_state(pipe, &state);
+}
+
+void *graw_parse_fragment_shader(struct pipe_context *pipe,
+ const char *text)
+{
+ struct tgsi_token tokens[1024];
+ struct pipe_shader_state state;
+
+ if (!tgsi_text_translate(text, tokens, Elements(tokens)))
+ return NULL;
+
+ state.tokens = tokens;
+ return pipe->create_fs_state(pipe, &state);
+}
+
#include "pipe/p_compiler.h"
+#include "pipe/p_context.h"
#include "util/u_debug.h"
#include "util/u_memory.h"
#include "target-helpers/wrap_screen.h"
static struct {
Display *display;
+ void (*draw)(void);
} graw;
-struct pipe_screen *
-graw_init( void )
+static struct pipe_screen *
+graw_create_screen( void )
{
const char *default_driver;
const char *driver;
struct pipe_screen *screen = NULL;
struct sw_winsys *winsys = NULL;
- graw.display = XOpenDisplay(NULL);
- if (graw.display == NULL)
- return NULL;
-
/* Create the underlying winsys, which performs presents to Xlib
* drawables:
*/
-void *
-graw_create_window( int x,
- int y,
- unsigned width,
- unsigned height,
- enum pipe_format format )
+struct pipe_screen *
+graw_create_window_and_screen( int x,
+ int y,
+ unsigned width,
+ unsigned height,
+ enum pipe_format format,
+ void **handle)
{
- struct xlib_drawable *handle = NULL;
+ struct pipe_screen *screen = NULL;
+ struct xlib_drawable *xlib_handle = NULL;
XSetWindowAttributes attr;
Window root;
Window win = 0;
int n;
int scrnum;
+ graw.display = XOpenDisplay(NULL);
+ if (graw.display == NULL)
+ return NULL;
scrnum = DefaultScreen( graw.display );
root = RootWindow( graw.display, scrnum );
if (graw.display == NULL)
goto fail;
- handle = CALLOC_STRUCT(xlib_drawable);
- if (handle == NULL)
+ xlib_handle = CALLOC_STRUCT(xlib_drawable);
+ if (xlib_handle == NULL)
goto fail;
None, (char **)NULL, 0, &sizehints);
}
- XFree(visinfo);
XMapWindow(graw.display, win);
while (1) {
XEvent e;
}
}
- handle->visual = visinfo->visual;
- handle->drawable = (Drawable)win;
- handle->depth = visinfo->depth;
- return (void *)handle;
+ xlib_handle->visual = visinfo->visual;
+ xlib_handle->drawable = (Drawable)win;
+ xlib_handle->depth = visinfo->depth;
+ *handle = (void *)xlib_handle;
+
+ screen = graw_create_screen();
+ if (screen == NULL)
+ goto fail;
-fail:
- FREE(handle);
XFree(visinfo);
+ return screen;
+
+fail:
+ if (screen)
+ screen->destroy(screen);
+
+ if (xlib_handle)
+ FREE(xlib_handle);
+
+ if (visinfo)
+ XFree(visinfo);
if (win)
XDestroyWindow(graw.display, win);
}
+void
+graw_set_display_func( void (*draw)( void ) )
+{
+ graw.draw = draw;
+}
+
void
-graw_destroy_window( void *xlib_drawable )
+graw_main_loop( void )
{
+ int i;
+ for (i = 0; i < 10; i++) {
+ graw.draw();
+ sleep(1);
+ }
}
env.Prepend(LIBS = ['graw'])
progs = [
- 'clear'
+ 'clear',
+ 'tri',
+ 'quad-tex',
]
for prog in progs:
static const int WIDTH = 300;
static const int HEIGHT = 300;
-int main( int argc, char *argv[] )
+struct pipe_screen *screen;
+struct pipe_context *ctx;
+struct pipe_surface *surf;
+static void *window = NULL;
+
+static void draw( void )
+{
+ float clear_color[4] = {1,0,1,1};
+
+ ctx->clear(ctx, PIPE_CLEAR_COLOR, clear_color, 0, 0);
+ ctx->flush(ctx, PIPE_FLUSH_RENDER_CACHE, NULL);
+
+#if 0
+ /* At the moment, libgraw leaks out/makes available some of the
+ * symbols from gallium/auxiliary, including these debug helpers.
+ * Will eventually want to bless some of these paths, and lock the
+ * others down so they aren't accessible from test programs.
+ *
+ * This currently just happens to work on debug builds - a release
+ * build will probably fail to link here:
+ */
+ debug_dump_surface_bmp(ctx, "result.bmp", surf);
+#endif
+
+ screen->flush_frontbuffer(screen, surf, window);
+}
+
+static void init( void )
{
- struct pipe_screen *screen;
- struct pipe_context *pipe;
- struct pipe_surface *surf;
struct pipe_framebuffer_state fb;
struct pipe_resource *tex, templat;
- void *window = NULL;
- float clear_color[4] = {1,0,1,1};
int i;
- screen = graw_init();
- if (screen == NULL)
- exit(1);
-
+ /* It's hard to say whether window or screen should be created
+ * first. Different environments would prefer one or the other.
+ *
+ * Also, no easy way of querying supported formats if the screen
+ * cannot be created first.
+ */
for (i = 0;
window == NULL && formats[i] != PIPE_FORMAT_NONE;
i++) {
- window = graw_create_window(0,0,300,300, formats[i]);
+ screen = graw_create_window_and_screen(0,0,300,300,
+ formats[i],
+ &window);
}
-
if (window == NULL)
exit(2);
- pipe = screen->context_create(screen, NULL);
- if (pipe == NULL)
+ ctx = screen->context_create(screen, NULL);
+ if (ctx == NULL)
exit(3);
templat.target = PIPE_TEXTURE_2D;
templat.last_level = 0;
templat.nr_samples = 1;
templat.bind = (PIPE_BIND_RENDER_TARGET |
- PIPE_BIND_DISPLAY_TARGET);
+ PIPE_BIND_DISPLAY_TARGET);
tex = screen->resource_create(screen,
- &templat);
+ &templat);
if (tex == NULL)
exit(4);
fb.height = HEIGHT;
fb.cbufs[0] = surf;
- pipe->set_framebuffer_state(pipe, &fb);
- pipe->clear(pipe, PIPE_CLEAR_COLOR, clear_color, 0, 0);
- pipe->flush(pipe, PIPE_FLUSH_RENDER_CACHE, NULL);
+ ctx->set_framebuffer_state(ctx, &fb);
+}
- /* At the moment, libgraw includes/makes available all the symbols
- * from gallium/auxiliary, including these debug helpers. Will
- * eventually want to bless some of these paths, and lock the
- * others down so they aren't accessible from test programs.
- */
- if (0)
- debug_dump_surface_bmp(pipe, "result.bmp", surf);
- screen->flush_frontbuffer(screen, surf, window);
- os_time_sleep(100*1000*100);
+int main( int argc, char *argv[] )
+{
+ init();
+ graw_set_display_func( draw );
+ graw_main_loop();
return 0;
}
--- /dev/null
+/* Display a cleared blue window. This demo has no dependencies on
+ * any utility code, just the graw interface and gallium.
+ */
+
+#include "state_tracker/graw.h"
+#include "pipe/p_screen.h"
+#include "pipe/p_context.h"
+#include "pipe/p_shader_tokens.h"
+#include "pipe/p_state.h"
+#include "pipe/p_defines.h"
+#include <unistd.h> /* for sleep() */
+
+#include "util/u_debug.h" /* debug_dump_surface_bmp() */
+#include "util/u_inlines.h"
+#include "util/u_memory.h" /* Offset() */
+#include "util/u_box.h"
+
+enum pipe_format formats[] = {
+ PIPE_FORMAT_R8G8B8A8_UNORM,
+ PIPE_FORMAT_B8G8R8A8_UNORM,
+ PIPE_FORMAT_NONE
+};
+
+static const int WIDTH = 300;
+static const int HEIGHT = 300;
+
+static struct pipe_screen *screen = NULL;
+static struct pipe_context *ctx = NULL;
+static struct pipe_resource *rttex = NULL;
+static struct pipe_resource *samptex = NULL;
+static struct pipe_surface *surf = NULL;
+static struct pipe_sampler_view *sv = NULL;
+static void *sampler = NULL;
+static void *window = NULL;
+
+struct vertex {
+ float position[4];
+ float color[4];
+};
+
+static struct vertex vertices[] =
+{
+ { { 0.9, -0.9, 0.0, 1.0 },
+ { 1, 0, 0, 1 } },
+
+ { { 0.9, 0.9, 0.0, 1.0 },
+ { 1, 1, 0, 1 } },
+
+ { {-0.9, 0.9, 0.0, 1.0 },
+ { 0, 1, 0, 1 } },
+
+ { {-0.9, -0.9, 0.0, 1.0 },
+ { 0, 0, 0, 1 } },
+};
+
+
+
+
+static void set_viewport( float x, float y,
+ float width, float height,
+ float near, float far)
+{
+ float z = far;
+ float half_width = (float)width / 2.0f;
+ float half_height = (float)height / 2.0f;
+ float half_depth = ((float)far - (float)near) / 2.0f;
+ struct pipe_viewport_state vp;
+
+ vp.scale[0] = half_width;
+ vp.scale[1] = half_height;
+ vp.scale[2] = half_depth;
+ vp.scale[3] = 1.0f;
+
+ vp.translate[0] = half_width + x;
+ vp.translate[1] = half_height + y;
+ vp.translate[2] = half_depth + z;
+ vp.translate[3] = 0.0f;
+
+ ctx->set_viewport_state( ctx, &vp );
+}
+
+static void set_vertices( void )
+{
+ struct pipe_vertex_element ve[2];
+ struct pipe_vertex_buffer vbuf;
+ void *handle;
+
+ memset(ve, 0, sizeof ve);
+
+ ve[0].src_offset = Offset(struct vertex, position);
+ ve[0].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
+ ve[1].src_offset = Offset(struct vertex, color);
+ ve[1].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
+
+ handle = ctx->create_vertex_elements_state(ctx, 2, ve);
+ ctx->bind_vertex_elements_state(ctx, handle);
+
+
+ vbuf.stride = sizeof( struct vertex );
+ vbuf.max_index = sizeof(vertices) / vbuf.stride;
+ vbuf.buffer_offset = 0;
+ vbuf.buffer = screen->user_buffer_create(screen,
+ vertices,
+ sizeof(vertices),
+ PIPE_BIND_VERTEX_BUFFER);
+
+ ctx->set_vertex_buffers(ctx, 1, &vbuf);
+}
+
+static void set_vertex_shader( void )
+{
+ void *handle;
+ const char *text =
+ "VERT\n"
+ "DCL IN[0]\n"
+ "DCL IN[1]\n"
+ "DCL OUT[0], POSITION\n"
+ "DCL OUT[1], GENERIC[0]\n"
+ " 0: MOV OUT[1], IN[1]\n"
+ " 1: MOV OUT[0], IN[0]\n"
+ " 2: END\n";
+
+ handle = graw_parse_vertex_shader(ctx, text);
+ ctx->bind_vs_state(ctx, handle);
+}
+
+static void set_fragment_shader( void )
+{
+ void *handle;
+ const char *text =
+ "FRAG\n"
+ "DCL IN[0], GENERIC[0], PERSPECTIVE\n"
+ "DCL OUT[0], COLOR\n"
+ "DCL TEMP[0]\n"
+ "DCL SAMP[0]\n"
+ " 0: TXP TEMP[0], IN[0], SAMP[0], 2D\n"
+ " 1: MOV OUT[0], TEMP[0]\n"
+ " 2: END\n";
+
+ handle = graw_parse_fragment_shader(ctx, text);
+ ctx->bind_fs_state(ctx, handle);
+}
+
+
+static void draw( void )
+{
+ float clear_color[4] = {.5,.5,.5,1};
+
+ ctx->clear(ctx, PIPE_CLEAR_COLOR, clear_color, 0, 0);
+ ctx->draw_arrays(ctx, PIPE_PRIM_QUADS, 0, 4);
+ ctx->flush(ctx, PIPE_FLUSH_RENDER_CACHE, NULL);
+
+#if 0
+ /* At the moment, libgraw leaks out/makes available some of the
+ * symbols from gallium/auxiliary, including these debug helpers.
+ * Will eventually want to bless some of these paths, and lock the
+ * others down so they aren't accessible from test programs.
+ *
+ * This currently just happens to work on debug builds - a release
+ * build will probably fail to link here:
+ */
+ debug_dump_surface_bmp(ctx, "result.bmp", surf);
+#endif
+
+ screen->flush_frontbuffer(screen, surf, window);
+}
+
+#define SIZE 16
+
+static void init_tex( void )
+{
+ struct pipe_sampler_view sv_template;
+ struct pipe_sampler_state sampler_desc;
+ struct pipe_resource templat;
+ struct pipe_box box;
+ ubyte tex2d[SIZE][SIZE][4];
+ int s, t;
+
+#if (SIZE != 2)
+ for (s = 0; s < SIZE; s++) {
+ for (t = 0; t < SIZE; t++) {
+ if (0) {
+ int x = (s ^ t) & 1;
+ tex2d[t][s][0] = (x) ? 0 : 63;
+ tex2d[t][s][1] = (x) ? 0 : 128;
+ tex2d[t][s][2] = 0;
+ tex2d[t][s][3] = 0xff;
+ }
+ else {
+ int x = ((s ^ t) >> 2) & 1;
+ tex2d[t][s][0] = s*255/(SIZE-1);
+ tex2d[t][s][1] = t*255/(SIZE-1);
+ tex2d[t][s][2] = (x) ? 0 : 128;
+ tex2d[t][s][3] = 0xff;
+ }
+ }
+ }
+#else
+ tex2d[0][0][0] = 0;
+ tex2d[0][0][1] = 255;
+ tex2d[0][0][2] = 255;
+ tex2d[0][0][3] = 0;
+
+ tex2d[0][1][0] = 0;
+ tex2d[0][1][1] = 0;
+ tex2d[0][1][2] = 255;
+ tex2d[0][1][3] = 255;
+
+ tex2d[1][0][0] = 255;
+ tex2d[1][0][1] = 255;
+ tex2d[1][0][2] = 0;
+ tex2d[1][0][3] = 255;
+
+ tex2d[1][1][0] = 255;
+ tex2d[1][1][1] = 0;
+ tex2d[1][1][2] = 0;
+ tex2d[1][1][3] = 255;
+#endif
+
+ templat.target = PIPE_TEXTURE_2D;
+ templat.format = PIPE_FORMAT_B8G8R8A8_UNORM;
+ templat.width0 = SIZE;
+ templat.height0 = SIZE;
+ templat.depth0 = 1;
+ templat.last_level = 0;
+ templat.nr_samples = 1;
+ templat.bind = PIPE_BIND_SAMPLER_VIEW;
+
+
+ samptex = screen->resource_create(screen,
+ &templat);
+ if (samptex == NULL)
+ exit(4);
+
+ u_box_2d(0,0,SIZE,SIZE, &box);
+
+ ctx->transfer_inline_write(ctx,
+ samptex,
+ u_subresource(0,0),
+ PIPE_TRANSFER_WRITE,
+ &box,
+ tex2d,
+ sizeof tex2d[0],
+ sizeof tex2d);
+
+ /* Possibly read back & compare against original data:
+ */
+ if (0)
+ {
+ struct pipe_transfer *t;
+ uint32_t *ptr;
+ t = pipe_get_transfer(ctx, samptex,
+ 0, 0, 0, /* face, level, zslice */
+ PIPE_TRANSFER_READ,
+ 0, 0, SIZE, SIZE); /* x, y, width, height */
+
+ ptr = ctx->transfer_map(ctx, t);
+
+ if (memcmp(ptr, tex2d, sizeof tex2d) != 0) {
+ assert(0);
+ exit(9);
+ }
+
+ ctx->transfer_unmap(ctx, t);
+
+ ctx->transfer_destroy(ctx, t);
+ }
+
+ memset(&sv_template, 0, sizeof sv_template);
+ sv_template.format = samptex->format;
+ sv_template.texture = samptex;
+ sv_template.first_level = 0;
+ sv_template.last_level = 0;
+ sv_template.swizzle_r = 0;
+ sv_template.swizzle_g = 1;
+ sv_template.swizzle_b = 2;
+ sv_template.swizzle_a = 3;
+ sv = ctx->create_sampler_view(ctx, samptex, &sv_template);
+ if (sv == NULL)
+ exit(5);
+
+ ctx->set_fragment_sampler_views(ctx, 1, &sv);
+
+
+ memset(&sampler_desc, 0, sizeof sampler_desc);
+ sampler_desc.wrap_s = PIPE_TEX_WRAP_REPEAT;
+ sampler_desc.wrap_t = PIPE_TEX_WRAP_REPEAT;
+ sampler_desc.wrap_r = PIPE_TEX_WRAP_REPEAT;
+ sampler_desc.min_img_filter = PIPE_TEX_FILTER_NEAREST;
+ sampler_desc.min_mip_filter = PIPE_TEX_MIPFILTER_NONE;
+ sampler_desc.mag_img_filter = PIPE_TEX_FILTER_NEAREST;
+ sampler_desc.compare_mode = PIPE_TEX_COMPARE_NONE;
+ sampler_desc.compare_func = 0;
+ sampler_desc.normalized_coords = 1;
+ sampler_desc.max_anisotropy = 0;
+
+ sampler = ctx->create_sampler_state(ctx, &sampler_desc);
+ if (sampler == NULL)
+ exit(6);
+
+ ctx->bind_fragment_sampler_states(ctx, 1, &sampler);
+
+}
+
+static void init( void )
+{
+ struct pipe_framebuffer_state fb;
+ struct pipe_resource templat;
+ int i;
+
+ /* It's hard to say whether window or screen should be created
+ * first. Different environments would prefer one or the other.
+ *
+ * Also, no easy way of querying supported formats if the screen
+ * cannot be created first.
+ */
+ for (i = 0;
+ window == NULL && formats[i] != PIPE_FORMAT_NONE;
+ i++) {
+
+ screen = graw_create_window_and_screen(0,0,300,300,
+ formats[i],
+ &window);
+ }
+
+ ctx = screen->context_create(screen, NULL);
+ if (ctx == NULL)
+ exit(3);
+
+ templat.target = PIPE_TEXTURE_2D;
+ templat.format = formats[i];
+ templat.width0 = WIDTH;
+ templat.height0 = HEIGHT;
+ templat.depth0 = 1;
+ templat.last_level = 0;
+ templat.nr_samples = 1;
+ templat.bind = (PIPE_BIND_RENDER_TARGET |
+ PIPE_BIND_DISPLAY_TARGET);
+
+ rttex = screen->resource_create(screen,
+ &templat);
+ if (rttex == NULL)
+ exit(4);
+
+ surf = screen->get_tex_surface(screen, rttex, 0, 0, 0,
+ PIPE_BIND_RENDER_TARGET |
+ PIPE_BIND_DISPLAY_TARGET);
+ if (surf == NULL)
+ exit(5);
+
+ memset(&fb, 0, sizeof fb);
+ fb.nr_cbufs = 1;
+ fb.width = WIDTH;
+ fb.height = HEIGHT;
+ fb.cbufs[0] = surf;
+
+ ctx->set_framebuffer_state(ctx, &fb);
+
+ {
+ struct pipe_blend_state blend;
+ void *handle;
+ memset(&blend, 0, sizeof blend);
+ blend.rt[0].colormask = PIPE_MASK_RGBA;
+ handle = ctx->create_blend_state(ctx, &blend);
+ ctx->bind_blend_state(ctx, handle);
+ }
+
+ {
+ struct pipe_depth_stencil_alpha_state depthstencil;
+ void *handle;
+ memset(&depthstencil, 0, sizeof depthstencil);
+ handle = ctx->create_depth_stencil_alpha_state(ctx, &depthstencil);
+ ctx->bind_depth_stencil_alpha_state(ctx, handle);
+ }
+
+ {
+ struct pipe_rasterizer_state rasterizer;
+ void *handle;
+ memset(&rasterizer, 0, sizeof rasterizer);
+ rasterizer.front_winding = PIPE_WINDING_CW;
+ rasterizer.cull_mode = PIPE_WINDING_NONE;
+ rasterizer.gl_rasterization_rules = 1;
+ handle = ctx->create_rasterizer_state(ctx, &rasterizer);
+ ctx->bind_rasterizer_state(ctx, handle);
+ }
+
+ set_viewport(0, 0, WIDTH, HEIGHT, 30, 1000);
+
+ init_tex();
+
+ set_vertices();
+ set_vertex_shader();
+ set_fragment_shader();
+}
+
+
+int main( int argc, char *argv[] )
+{
+ init();
+
+ graw_set_display_func( draw );
+ graw_main_loop();
+ return 0;
+}
boolean radeon_drm_bufmgr_is_buffer_referenced(struct pb_buffer *_buf,
enum r300_reference_domain domain);
+
+void radeon_drm_bufmgr_wait(struct pb_buffer *_buf);
+
#endif
make_empty_list(&mgr->buffer_map_list);
}
+
+void radeon_drm_bufmgr_wait(struct pb_buffer *_buf)
+{
+ struct radeon_drm_buffer *buf = get_drm_buffer(_buf);
+
+ radeon_bo_wait(buf->bo);
+}
pb_unmap(_buf);
}
+static void radeon_r300_winsys_buffer_wait(struct r300_winsys_screen *ws,
+ struct r300_winsys_buffer *buf)
+{
+ struct pb_buffer *_buf = radeon_pb_buffer(buf);
+ radeon_drm_bufmgr_wait(_buf);
+}
+
static void radeon_r300_winsys_buffer_reference(struct r300_winsys_screen *rws,
struct r300_winsys_buffer **pdst,
struct r300_winsys_buffer *src)
ws->base.buffer_get_tiling = radeon_r300_winsys_buffer_get_tiling;
ws->base.buffer_map = radeon_r300_winsys_buffer_map;
ws->base.buffer_unmap = radeon_r300_winsys_buffer_unmap;
+ ws->base.buffer_wait = radeon_r300_winsys_buffer_wait;
ws->base.buffer_reference = radeon_r300_winsys_buffer_reference;
ws->base.buffer_from_handle = radeon_r300_winsys_buffer_from_handle;
ws->base.buffer_get_handle = radeon_r300_winsys_buffer_get_handle;
* XXX Why don't we just get the template.
*/
memset(&templ, 0, sizeof(templ));
+ templ.target = PIPE_TEXTURE_2D;
templ.width0 = width;
templ.height0 = height;
templ.format = format;
return wsw_dt_wrap_texture(wsw, tex, stride);
}
+static boolean
+wsw_dt_get_handle(struct sw_winsys *ws,
+ struct sw_displaytarget *dt,
+ struct winsys_handle *whandle)
+{
+ struct wrapper_sw_winsys *wsw = wrapper_sw_winsys(ws);
+ struct wrapper_sw_displaytarget *wdt = wrapper_sw_displaytarget(dt);
+ struct pipe_resource *tex = wdt->tex;
+
+ return wsw->screen->resource_get_handle(wsw->screen, tex, whandle);
+}
+
static void *
wsw_dt_map(struct sw_winsys *ws,
struct sw_displaytarget *dt,
wsw->base.displaytarget_create = wsw_dt_create;
wsw->base.displaytarget_from_handle = wsw_dt_from_handle;
+ wsw->base.displaytarget_get_handle = wsw_dt_get_handle;
wsw->base.displaytarget_map = wsw_dt_map;
wsw->base.displaytarget_unmap = wsw_dt_unmap;
wsw->base.displaytarget_destroy = wsw_dt_destroy;
static void
dri2FlushFrontBuffer(__DRIdrawable *driDrawable, void *loaderPrivate)
{
+ __GLXDRIdrawablePrivate *pdraw = loaderPrivate;
+ __GLXdisplayPrivate *priv = __glXInitialize(pdraw->base.psc->dpy);
+ __GLXDRIdisplayPrivate *pdp = (__GLXDRIdisplayPrivate *)priv->dri2Display;
+
+ /* Old servers don't send invalidate events */
+ if (!pdp->invalidateAvailable)
+ dri2InvalidateBuffers(priv->dpy, pdraw->base.drawable);
+
dri2WaitGL(loaderPrivate);
}
(*pdraw->psc->f->flush)(pdraw->driDrawable);
#endif
+ /* Old servers don't send invalidate events */
+ if (!pdp->invalidateAvailable)
+ dri2InvalidateBuffers(dpyPriv->dpy, pdraw->drawable);
+
/* Old servers can't handle swapbuffers */
if (!pdp->swapAvailable) {
dri2CopySubBuffer(pdraw, 0, 0, priv->width, priv->height);
return 0;
}
- /* Old servers don't send invalidate events */
- if (!pdp->invalidateAvailable)
- dri2InvalidateBuffers(dpyPriv->dpy, pdraw->drawable);
-
#ifdef X_DRI2SwapBuffers
DRI2SwapBuffers(pdraw->psc->dpy, pdraw->xDrawable, target_msc, divisor,
remainder, &ret);
pdp->loader_extensions[i++] = &systemTimeExtension.base;
#ifdef __DRI_USE_INVALIDATE
- if (pdp->invalidateAvailable)
- pdp->loader_extensions[i++] = &dri2UseInvalidate.base;
- pdp->loader_extensions[i++] = NULL;
+ pdp->loader_extensions[i++] = &dri2UseInvalidate.base;
#endif
+ pdp->loader_extensions[i++] = NULL;
return &pdp->base;
}
pcedit-es1 = \
$(pcedit) \
- -e 's,@GLESv1_CM_REQ_PRIV@,$(GLESv1_CM_REQ_PRIV),' \
+ -e 's,@GLESv1_CM_PC_REQ_PRIV@,$(GLESv1_CM_PC_REQ_PRIV),' \
-e 's,@GLESv1_CM_PC_LIB_PRIV@,$(GLESv1_CM_PC_LIB_PRIV),' \
-e 's,@GLESv1_CM_PC_CFLAGS@,$(GLESv1_CM_PC_CFLAGS),' \
-e 's,@GLESv1_CM_LIB@,$(GLESv1_CM_LIB),'
#include "brw_state.h"
#include "brw_clip.h"
-
#define FRONT_UNFILLED_BIT 0x1
#define BACK_UNFILLED_BIT 0x2
*/
program = brw_get_program(&c.func, &program_size);
+ if (INTEL_DEBUG & DEBUG_CLIP) {
+ printf("clip:\n");
+ for (i = 0; i < program_size / sizeof(struct brw_instruction); i++)
+ brw_disasm(stdout, &((struct brw_instruction *)program)[i],
+ intel->gen);
+ printf("\n");
+ }
+
/* Upload
*/
dri_bo_unreference(brw->clip.prog_bo);
GLboolean need_direction;
- GLuint last_mrf;
-
GLuint header_position_offset;
GLuint offset[VERT_ATTRIB_MAX];
};
void brw_clip_tri_flat_shade( struct brw_clip_compile *c )
{
struct brw_compile *p = &c->func;
- struct brw_instruction *is_poly;
+ struct brw_instruction *is_poly, *is_trifan;
struct brw_reg tmp0 = c->reg.loopcount; /* handy temporary */
brw_AND(p, tmp0, get_element_ud(c->reg.R0, 2), brw_imm_ud(PRIM_MASK));
is_poly = brw_ELSE(p, is_poly);
{
if (c->key.pv_first) {
- brw_clip_copy_colors(c, 1, 0);
- brw_clip_copy_colors(c, 2, 0);
+ brw_CMP(p,
+ vec1(brw_null_reg()),
+ BRW_CONDITIONAL_EQ,
+ tmp0,
+ brw_imm_ud(_3DPRIM_TRIFAN));
+ is_trifan = brw_IF(p, BRW_EXECUTE_1);
+ {
+ brw_clip_copy_colors(c, 0, 1);
+ brw_clip_copy_colors(c, 2, 1);
+ }
+ is_trifan = brw_ELSE(p, is_trifan);
+ {
+ brw_clip_copy_colors(c, 1, 0);
+ brw_clip_copy_colors(c, 2, 0);
+ }
+ brw_ENDIF(p, is_trifan);
}
else {
brw_clip_copy_colors(c, 0, 2);
GLuint header)
{
struct brw_compile *p = &c->func;
- GLuint start = c->last_mrf;
brw_clip_ff_sync(c);
assert(!(allocate && eot));
-
- /* Cycle through mrf regs - probably futile as we have to wait for
- * the allocation response anyway. Also, the order this function
- * is invoked doesn't correspond to the order the instructions will
- * be executed, so it won't have any effect in many cases.
- */
-#if 0
- if (start + c->nr_regs + 1 >= MAX_MRF)
- start = 0;
- c->last_mrf = start + c->nr_regs + 1;
-#endif
-
/* Copy the vertex from vertn into m1..mN+1:
*/
- brw_copy_from_indirect(p, brw_message_reg(start+1), vert, c->nr_regs);
+ brw_copy_from_indirect(p, brw_message_reg(1), vert, c->nr_regs);
/* Overwrite PrimType and PrimStart in the message header, for
* each vertex in turn:
*/
brw_urb_WRITE(p,
allocate ? c->reg.R0 : retype(brw_null_reg(), BRW_REGISTER_TYPE_UD),
- start,
+ 0,
c->reg.R0,
allocate,
1, /* used */
need_ff_sync = brw_IF(p, BRW_EXECUTE_1);
{
brw_OR(p, c->reg.ff_sync, c->reg.ff_sync, brw_imm_ud(0x1));
- brw_ff_sync(p,
- c->reg.R0,
- 0,
- c->reg.R0,
- 1,
- 1, /* used */
- 1, /* msg length */
- 1, /* response length */
- 0, /* eot */
- 1, /* write compelete */
- 0, /* urb offset */
- BRW_URB_SWIZZLE_NONE);
+ brw_ff_sync(p,
+ c->reg.R0,
+ 0,
+ c->reg.R0,
+ 1, /* allocate */
+ 1, /* response length */
+ 0 /* eot */);
}
brw_ENDIF(p, need_ff_sync);
brw_set_predicate_control(p, BRW_PREDICATE_NONE);
ctx->VertexProgram._MaintainTnlProgram = GL_TRUE;
ctx->FragmentProgram._MaintainTexEnvProgram = GL_TRUE;
- make_empty_list(&brw->query.active_head);
-
brw_draw_init( brw );
return GL_TRUE;
struct brw_query_object {
struct gl_query_object Base;
- /** Doubly linked list of active query objects in the context. */
- struct brw_query_object *prev, *next;
-
/** Last query BO associated with this query. */
dri_bo *bo;
/** First index in bo with query data for this object. */
int first_index;
/** Last index in bo with query data for this object. */
int last_index;
-
- /* Total count of pixels from previous BOs */
- unsigned int count;
};
} cc;
struct {
- struct brw_query_object active_head;
+ struct brw_query_object *obj;
dri_bo *bo;
int index;
GLboolean active;
void brw_upload_cs_urb_state(struct brw_context *brw);
/* brw_disasm.c */
-int brw_disasm (FILE *file, struct brw_instruction *inst);
+int brw_disasm (FILE *file, struct brw_instruction *inst, int gen);
/*======================================================================
* Inline conversion functions. These are better-typed than the
#define CMD_BINDING_TABLE_PTRS 0x7801
# define GEN6_BINDING_TABLE_MODIFY_VS (1 << 8)
# define GEN6_BINDING_TABLE_MODIFY_GS (1 << 9)
-# define GEN6_BINDING_TABLE_MODIFY_PS (1 << 10)
+# define GEN6_BINDING_TABLE_MODIFY_PS (1 << 12)
#define CMD_3D_SAMPLER_STATE_POINTERS 0x7802 /* SNB+ */
# define PS_SAMPLER_STATE_CHANGE (1 << 12)
[1] = "partial_precision"
};
+char *urb_opcode[2] = {
+ [0] = "urb_write",
+ [1] = "ff_sync",
+};
+
char *urb_swizzle[4] = {
[BRW_URB_SWIZZLE_NONE] = "",
[BRW_URB_SWIZZLE_INTERLEAVE] = "interleave",
}
}
-int brw_disasm (FILE *file, struct brw_instruction *inst)
+int brw_disasm (FILE *file, struct brw_instruction *inst, int gen)
{
int err = 0;
int space = 0;
}
if (inst->header.opcode == BRW_OPCODE_SEND) {
+ int target;
+
+ if (gen >= 5)
+ target = inst->bits2.send_gen5.sfid;
+ else
+ target = inst->bits3.generic.msg_target;
+
newline (file);
pad (file, 16);
space = 0;
err |= control (file, "target function", target_function,
- inst->bits3.generic.msg_target, &space);
- switch (inst->bits3.generic.msg_target) {
+ target, &space);
+
+ switch (target) {
case BRW_MESSAGE_TARGET_MATH:
err |= control (file, "math function", math_function,
inst->bits3.math.function, &space);
inst->bits3.dp_write.send_commit_msg);
break;
case BRW_MESSAGE_TARGET_URB:
- format (file, " %d", inst->bits3.urb.offset);
+ if (gen >= 5) {
+ format (file, " %d", inst->bits3.urb_gen5.offset);
+ } else {
+ format (file, " %d", inst->bits3.urb.offset);
+ }
+
space = 1;
+ if (gen >= 5) {
+ err |= control (file, "urb opcode", urb_opcode,
+ inst->bits3.urb_gen5.opcode, &space);
+ }
err |= control (file, "urb swizzle", urb_swizzle,
inst->bits3.urb.swizzle_control, &space);
err |= control (file, "urb allocate", urb_allocate,
0,
BRW_SURFACEFORMAT_R16_FLOAT,
BRW_SURFACEFORMAT_R16G16_FLOAT,
- 0, /* can't seem to render this one */
+ BRW_SURFACEFORMAT_R16G16B16A16_FLOAT,
BRW_SURFACEFORMAT_R16G16B16A16_FLOAT
};
GLuint msg_reg_nr,
struct brw_reg src0,
GLboolean allocate,
- GLboolean used,
- GLuint msg_length,
GLuint response_length,
- GLboolean eot,
- GLboolean writes_complete,
- GLuint offset,
- GLuint swizzle);
+ GLboolean eot);
void brw_fb_WRITE(struct brw_compile *p,
struct brw_reg dest,
}
-static void brw_set_ff_sync_message( struct brw_context *brw,
- struct brw_instruction *insn,
- GLboolean allocate,
- GLboolean used,
- GLuint msg_length,
- GLuint response_length,
- GLboolean end_of_thread,
- GLboolean complete,
- GLuint offset,
- GLuint swizzle_control )
+static void brw_set_ff_sync_message(struct brw_context *brw,
+ struct brw_instruction *insn,
+ GLboolean allocate,
+ GLuint response_length,
+ GLboolean end_of_thread)
{
brw_set_src1(insn, brw_imm_d(0));
- insn->bits3.urb_gen5.opcode = 1;
- insn->bits3.urb_gen5.offset = offset;
- insn->bits3.urb_gen5.swizzle_control = swizzle_control;
+ insn->bits3.urb_gen5.opcode = 1; /* FF_SYNC */
+ insn->bits3.urb_gen5.offset = 0; /* Not used by FF_SYNC */
+ insn->bits3.urb_gen5.swizzle_control = 0; /* Not used by FF_SYNC */
insn->bits3.urb_gen5.allocate = allocate;
- insn->bits3.urb_gen5.used = used;
- insn->bits3.urb_gen5.complete = complete;
+ insn->bits3.urb_gen5.used = 0; /* Not used by FF_SYNC */
+ insn->bits3.urb_gen5.complete = 0; /* Not used by FF_SYNC */
insn->bits3.urb_gen5.header_present = 1;
- insn->bits3.urb_gen5.response_length = response_length;
- insn->bits3.urb_gen5.msg_length = msg_length;
+ insn->bits3.urb_gen5.response_length = response_length; /* may be 1 or 0 */
+ insn->bits3.urb_gen5.msg_length = 1;
insn->bits3.urb_gen5.end_of_thread = end_of_thread;
insn->bits2.send_gen5.sfid = BRW_MESSAGE_TARGET_URB;
insn->bits2.send_gen5.end_of_thread = end_of_thread;
GLuint msg_reg_nr,
struct brw_reg src0,
GLboolean allocate,
- GLboolean used,
- GLuint msg_length,
GLuint response_length,
- GLboolean eot,
- GLboolean writes_complete,
- GLuint offset,
- GLuint swizzle)
+ GLboolean eot)
{
struct brw_instruction *insn = next_insn(p, BRW_OPCODE_SEND);
- assert(msg_length < 16);
-
brw_set_dest(insn, dest);
brw_set_src0(insn, src0);
brw_set_src1(insn, brw_imm_d(0));
insn->header.destreg__conditionalmod = msg_reg_nr;
brw_set_ff_sync_message(p->brw,
- insn,
- allocate,
- used,
- msg_length,
- response_length,
- eot,
- writes_complete,
- offset,
- swizzle);
+ insn,
+ allocate,
+ response_length,
+ eot);
}
*/
program = brw_get_program(&c.func, &program_size);
+ if (INTEL_DEBUG & DEBUG_GS) {
+ int i;
+
+ printf("gs:\n");
+ for (i = 0; i < program_size / sizeof(struct brw_instruction); i++)
+ brw_disasm(stdout, &((struct brw_instruction *)program)[i],
+ intel->gen);
+ printf("\n");
+ }
+
/* Upload
*/
dri_bo_unreference(brw->gs.prog_bo);
/* _NEW_LIGHT */
key->pv_first = (ctx->Light.ProvokingVertex == GL_FIRST_VERTEX_CONVENTION);
+ if (key->primitive == GL_QUADS && ctx->Light.ShadeModel != GL_FLAT) {
+ /* Provide consistent primitive order with brw_set_prim's
+ * optimization of single quads to trifans.
+ */
+ key->pv_first = GL_TRUE;
+ }
key->need_gs_prog = (key->hint_gs_always ||
brw->primitive == GL_QUADS ||
{
struct brw_compile *p = &c->func;
brw_MOV(p, get_element_ud(c->reg.R0, 1), brw_imm_ud(num_prim));
- brw_ff_sync(p,
- c->reg.R0,
- 0,
- c->reg.R0,
- 1,
- 1, /* used */
- 1, /* msg length */
- 1, /* response length */
- 0, /* eot */
- 1, /* write compelete */
- 0, /* urb offset */
- BRW_URB_SWIZZLE_NONE);
+ brw_ff_sync(p,
+ c->reg.R0,
+ 0,
+ c->reg.R0,
+ 1, /* allocate */
+ 1, /* response length */
+ 0 /* eot */);
}
* required for handling queries, so that we can be sure that we won't
* have to emit a batchbuffer without getting the ending PS_DEPTH_COUNT.
*/
-#include "main/simple_list.h"
#include "main/imports.h"
#include "brw_context.h"
query->first_index = -1;
query->last_index = -1;
- insert_at_head(&brw->query.active_head, query);
+ brw->query.obj = query;
intel->stats_wm++;
}
brw->query.bo = NULL;
}
- remove_from_list(query);
+ brw->query.obj = NULL;
intel->stats_wm--;
}
struct intel_context *intel = &brw->intel;
/* Skip if we're not doing any queries. */
- if (is_empty_list(&brw->query.active_head))
+ if (!brw->query.obj)
return;
/* Get a new query BO if we're going to need it. */
brw_emit_query_begin(struct brw_context *brw)
{
struct intel_context *intel = &brw->intel;
- struct brw_query_object *query;
+ struct brw_query_object *query = brw->query.obj;
/* Skip if we're not doing any queries, or we've emitted the start. */
- if (brw->query.active || is_empty_list(&brw->query.active_head))
+ if (!query || brw->query.active)
return;
BEGIN_BATCH(4);
OUT_BATCH(0);
ADVANCE_BATCH();
- foreach(query, &brw->query.active_head) {
- if (query->bo != brw->query.bo) {
- if (query->bo != NULL)
- brw_queryobj_get_results(query);
- dri_bo_reference(brw->query.bo);
- query->bo = brw->query.bo;
- query->first_index = brw->query.index;
- }
- query->last_index = brw->query.index;
+ if (query->bo != brw->query.bo) {
+ if (query->bo != NULL)
+ brw_queryobj_get_results(query);
+ dri_bo_reference(brw->query.bo);
+ query->bo = brw->query.bo;
+ query->first_index = brw->query.index;
}
+ query->last_index = brw->query.index;
brw->query.active = GL_TRUE;
}
static void compile_sf_prog( struct brw_context *brw,
struct brw_sf_prog_key *key )
{
+ struct intel_context *intel = &brw->intel;
struct brw_sf_compile c;
const GLuint *program;
GLuint program_size;
*/
program = brw_get_program(&c.func, &program_size);
+ if (INTEL_DEBUG & DEBUG_SF) {
+ printf("sf:\n");
+ for (i = 0; i < program_size / sizeof(struct brw_instruction); i++)
+ brw_disasm(stdout, &((struct brw_instruction *)program)[i],
+ intel->gen);
+ printf("\n");
+ }
+
/* Upload
*/
dri_bo_unreference(brw->sf.prog_bo);
break;
}
+ /* _NEW_POINT */
key.do_point_sprite = ctx->Point.PointSprite;
if (key.do_point_sprite) {
int i;
const GLuint *program;
struct brw_vs_compile c;
int aux_size;
+ int i;
memset(&c, 0, sizeof(c));
memcpy(&c.key, key, sizeof(*key));
c.prog_data.inputs_read |= 1<<VERT_ATTRIB_EDGEFLAG;
}
+ /* Put dummy slots into the VUE for the SF to put the replaced
+ * point sprite coords in. We shouldn't need these dummy slots,
+ * which take up precious URB space, but it would mean that the SF
+ * doesn't get nice aligned pairs of input coords into output
+ * coords, which would be a pain to handle.
+ */
+ for (i = 0; i < 8; i++) {
+ if (c.key.point_coord_replace & (1 << i))
+ c.prog_data.outputs_written |= BITFIELD64_BIT(VERT_RESULT_TEX0 + i);
+ }
+
if (0)
_mesa_print_program(&c.vp->program.Base);
struct brw_vs_prog_key key;
struct brw_vertex_program *vp =
(struct brw_vertex_program *)brw->vertex_program;
+ int i;
memset(&key, 0, sizeof(key));
key.copy_edgeflag = (ctx->Polygon.FrontMode != GL_FILL ||
ctx->Polygon.BackMode != GL_FILL);
+ /* _NEW_POINT */
+ if (ctx->Point.PointSprite) {
+ for (i = 0; i < 8; i++) {
+ if (ctx->Point.CoordReplace[i])
+ key.point_coord_replace |= (1 << i);
+ }
+ }
+
/* Make an early check for the key.
*/
dri_bo_unreference(brw->vs.prog_bo);
*/
const struct brw_tracked_state brw_vs_prog = {
.dirty = {
- .mesa = _NEW_TRANSFORM | _NEW_POLYGON,
+ .mesa = _NEW_TRANSFORM | _NEW_POLYGON | _NEW_POINT,
.brw = BRW_NEW_VERTEX_PROGRAM,
.cache = 0
},
GLuint program_string_id;
GLuint nr_userclip:4;
GLuint copy_edgeflag:1;
- GLuint pad:26;
+ GLuint point_coord_replace:8;
};
printf("vs-native:\n");
for (i = 0; i < p->nr_insn; i++)
- brw_disasm(stderr, &p->store[i]);
+ brw_disasm(stderr, &p->store[i], intel->gen);
printf("\n");
}
}
printf("wm-native:\n");
for (i = 0; i < p->nr_insn; i++)
- brw_disasm(stderr, &p->store[i]);
+ brw_disasm(stderr, &p->store[i], p->brw->intel.gen);
printf("\n");
}
}
if (INTEL_DEBUG & DEBUG_WM) {
printf("wm-native:\n");
for (i = 0; i < p->nr_insn; i++)
- brw_disasm(stderr, &p->store[i]);
+ brw_disasm(stderr, &p->store[i], intel->gen);
printf("\n");
}
}
struct intel_context *intel = batch->intel;
GLuint used = batch->ptr - batch->map;
- if (!intel->using_dri2_swapbuffers &&
- intel->first_post_swapbuffers_batch == NULL) {
+ if (intel->first_post_swapbuffers_batch == NULL) {
intel->first_post_swapbuffers_batch = intel->batch->buf;
drm_intel_bo_reference(intel->first_post_swapbuffers_batch);
}
OUT_BATCH(clear_val);
ADVANCE_BATCH();
+ if (intel->always_flush_cache)
+ intel_batchbuffer_emit_mi_flush(intel->batch);
+
if (buf == BUFFER_DEPTH || buf == BUFFER_STENCIL)
mask &= ~(BUFFER_BIT_DEPTH | BUFFER_BIT_STENCIL);
else
*/
if (intel->is_front_buffer_rendering)
intel->front_buffer_dirty = GL_TRUE;
+
+ /* Wait for the swapbuffers before the one we just emitted, so we
+ * don't get too many swaps outstanding for apps that are GPU-heavy
+ * but not CPU-heavy.
+ *
+ * We're using intelDRI2Flush (called from the loader before
+ * swapbuffer) and glFlush (for front buffer rendering) as the
+ * indicator that a frame is done and then throttle when we get
+ * here as we prepare to render the next frame. At this point for
+ * round trips for swap/copy and getting new buffers are done and
+ * we'll spend less time waiting on the GPU.
+ *
+ * Unfortunately, we don't have a handle to the batch containing
+ * the swap, and getting our hands on that doesn't seem worth it,
+ * so we just us the first batch we emitted after the last swap.
+ */
+ if (intel->need_throttle && intel->first_post_swapbuffers_batch) {
+ drm_intel_bo_wait_rendering(intel->first_post_swapbuffers_batch);
+ drm_intel_bo_unreference(intel->first_post_swapbuffers_batch);
+ intel->first_post_swapbuffers_batch = NULL;
+ intel->need_throttle = GL_FALSE;
+ }
}
static void
if (intel->saved_viewport)
intel->saved_viewport(ctx, x, y, w, h);
- if (!intel->using_dri2_swapbuffers &&
- !intel->meta.internal_viewport_call && ctx->DrawBuffer->Name == 0) {
+ if (!intel->meta.internal_viewport_call && ctx->DrawBuffer->Name == 0) {
dri2InvalidateDrawable(driContext->driDrawablePriv);
dri2InvalidateDrawable(driContext->driReadablePriv);
}
{ "buf", DEBUG_BUFMGR},
{ "reg", DEBUG_REGION},
{ "fbo", DEBUG_FBO},
- { "lock", DEBUG_LOCK},
+ { "gs", DEBUG_GS},
{ "sync", DEBUG_SYNC},
{ "prim", DEBUG_PRIMS },
{ "vert", DEBUG_VERTS },
{ "dri", DEBUG_DRI },
- { "dma", DEBUG_DMA },
+ { "sf", DEBUG_SF },
{ "san", DEBUG_SANITY },
{ "sleep", DEBUG_SLEEP },
{ "stats", DEBUG_STATS },
{ "glsl_force", DEBUG_GLSL_FORCE },
{ "urb", DEBUG_URB },
{ "vs", DEBUG_VS },
+ { "clip", DEBUG_CLIP },
{ NULL, 0 }
};
struct intel_context *intel = intel_context(ctx);
intel_flush(ctx);
-
intel_flush_front(ctx);
-
- /* We're using glFlush as an indicator that a frame is done, which is
- * what DRI2 does before calling SwapBuffers (and means we should catch
- * people doing front-buffer rendering, as well)..
- *
- * Wait for the swapbuffers before the one we just emitted, so we don't
- * get too many swaps outstanding for apps that are GPU-heavy but not
- * CPU-heavy.
- *
- * Unfortunately, we don't have a handle to the batch containing the swap,
- * and getting our hands on that doesn't seem worth it, so we just us the
- * first batch we emitted after the last swap.
- */
- if (!intel->using_dri2_swapbuffers &&
- intel->first_post_swapbuffers_batch != NULL) {
- drm_intel_bo_wait_rendering(intel->first_post_swapbuffers_batch);
- drm_intel_bo_unreference(intel->first_post_swapbuffers_batch);
- intel->first_post_swapbuffers_batch = NULL;
- }
+ intel->need_throttle = GL_TRUE;
}
void
driContextPriv->dri2.read_stamp = driReadPriv->dri2.stamp - 1;
intel_prepare_render(intel);
_mesa_make_current(&intel->ctx, fb, readFb);
+
+ /* We do this in intel_prepare_render() too, but intel->ctx.DrawBuffer
+ * is NULL at that point. We can't call _mesa_makecurrent()
+ * first, since we need the buffer size for the initial
+ * viewport. So just call intel_draw_buffer() again here. */
+ intel_draw_buffer(&intel->ctx, intel->ctx.DrawBuffer);
}
else {
_mesa_make_current(NULL, NULL, NULL);
struct intel_batchbuffer *batch;
drm_intel_bo *first_post_swapbuffers_batch;
+ GLboolean need_throttle;
GLboolean no_batch_wrap;
- GLboolean using_dri2_swapbuffers;
struct
{
#define DEBUG_BUFMGR 0x200
#define DEBUG_REGION 0x400
#define DEBUG_FBO 0x800
-#define DEBUG_LOCK 0x1000
+#define DEBUG_GS 0x1000
#define DEBUG_SYNC 0x2000
#define DEBUG_PRIMS 0x4000
#define DEBUG_VERTS 0x8000
#define DEBUG_DRI 0x10000
-#define DEBUG_DMA 0x20000
+#define DEBUG_SF 0x20000
#define DEBUG_SANITY 0x40000
#define DEBUG_SLEEP 0x80000
#define DEBUG_STATS 0x100000
#define DEBUG_URB 0x1000000
#define DEBUG_VS 0x2000000
#define DEBUG_GLSL_FORCE 0x4000000
+#define DEBUG_CLIP 0x8000000
#define DBG(...) do { \
if (INTEL_DEBUG & FILE_DEBUG_FLAG) \
if (intel->gen < 4)
INTEL_FIREVERTICES(intel);
+ intel->need_throttle = GL_TRUE;
+
if (intel->batch->map != intel->batch->ptr)
intel_batchbuffer_flush(intel->batch);
}
-static void
-intelDRI2Invalidate(__DRIdrawable *drawable)
-{
- struct intel_context *intel = drawable->driContextPriv->driverPrivate;
-
- intel->using_dri2_swapbuffers = GL_TRUE;
- dri2InvalidateDrawable(drawable);
-}
-
static const struct __DRI2flushExtensionRec intelFlushExtension = {
{ __DRI2_FLUSH, __DRI2_FLUSH_VERSION },
intelDRI2Flush,
- intelDRI2Invalidate,
+ dri2InvalidateDrawable,
};
static __DRIimage *
#include "intel_context.h"
#include "intel_tex.h"
#include "main/enums.h"
-
+#include "main/formats.h"
/**
* Choose hardware texture format given the user's glTexImage parameters.
int intel_compressed_num_bytes(GLuint mesaFormat)
{
- int bytes = 0;
- switch(mesaFormat) {
-
- case MESA_FORMAT_RGB_FXT1:
- case MESA_FORMAT_RGBA_FXT1:
- case MESA_FORMAT_RGB_DXT1:
- case MESA_FORMAT_RGBA_DXT1:
- bytes = 2;
- break;
-
- case MESA_FORMAT_RGBA_DXT3:
- case MESA_FORMAT_RGBA_DXT5:
- bytes = 4;
- default:
- break;
- }
-
- return bytes;
+ GLuint bw, bh;
+ GLuint block_size;
+
+ block_size = _mesa_get_format_bytes(mesaFormat);
+ _mesa_get_format_block_size(mesaFormat, &bw, &bh);
+
+ return block_size / bh;
}
radeon_dataflow.c \
radeon_dataflow_deadcode.c \
radeon_dataflow_swizzles.c \
+ radeon_optimize.c \
r3xx_fragprog.c \
r300_fragprog.c \
r300_fragprog_swizzle.c \
{MAKE_SWZ3(Z, X, Y), R300_ALU_ARGC_SRC0C_ZXY, 1},
{MAKE_SWZ3(W, Z, Y), R300_ALU_ARGC_SRC0CA_WZY, 1},
{MAKE_SWZ3(ONE, ONE, ONE), R300_ALU_ARGC_ONE, 0},
- {MAKE_SWZ3(ZERO, ZERO, ZERO), R300_ALU_ARGC_ZERO, 0}
+ {MAKE_SWZ3(ZERO, ZERO, ZERO), R300_ALU_ARGC_ZERO, 0},
+ {MAKE_SWZ3(HALF, HALF, HALF), R300_ALU_ARGC_HALF, 0}
};
static const int num_native_swizzles = sizeof(native_swizzles)/sizeof(native_swizzles[0]);
case RC_SWIZZLE_W: return R300_ALU_ARGA_SRC0A + src;
case RC_SWIZZLE_ONE: return R300_ALU_ARGA_ONE;
case RC_SWIZZLE_ZERO: return R300_ALU_ARGA_ZERO;
+ case RC_SWIZZLE_HALF: return R300_ALU_ARGA_HALF;
default: return R300_ALU_ARGA_ONE;
}
}
debug_program_log(c, "after deadcode");
+ rc_optimize(&c->Base);
+
+ debug_program_log(c, "after dataflow optimize");
+
rc_dataflow_swizzles(&c->Base);
if (c->Base.Error)
return;
#include "radeon_program.h"
-static void reads_normal(struct rc_instruction * fullinst, rc_read_write_fn cb, void * userdata)
+static void reads_normal(struct rc_instruction * fullinst, rc_read_write_chan_fn cb, void * userdata)
{
struct rc_sub_instruction * inst = &fullinst->U.I;
const struct rc_opcode_info * opcode = rc_get_opcode_info(inst->Opcode);
refmask &= RC_MASK_XYZW;
- for(unsigned int chan = 0; chan < 4; ++chan) {
- if (GET_BIT(refmask, chan)) {
- cb(userdata, fullinst, inst->SrcReg[src].File, inst->SrcReg[src].Index, chan);
- }
- }
+ if (refmask)
+ cb(userdata, fullinst, inst->SrcReg[src].File, inst->SrcReg[src].Index, refmask);
if (refmask && inst->SrcReg[src].RelAddr)
cb(userdata, fullinst, RC_FILE_ADDRESS, 0, RC_MASK_X);
}
}
-static void reads_pair(struct rc_instruction * fullinst, rc_read_write_fn cb, void * userdata)
+static void reads_pair(struct rc_instruction * fullinst, rc_read_write_mask_fn cb, void * userdata)
{
struct rc_pair_instruction * inst = &fullinst->U.P;
unsigned int refmasks[3] = { 0, 0, 0 };
}
for(unsigned int src = 0; src < 3; ++src) {
- if (inst->RGB.Src[src].Used) {
- for(unsigned int chan = 0; chan < 3; ++chan) {
- if (GET_BIT(refmasks[src], chan))
- cb(userdata, fullinst, inst->RGB.Src[src].File, inst->RGB.Src[src].Index, chan);
- }
- }
+ if (inst->RGB.Src[src].Used && (refmasks[src] & RC_MASK_XYZ))
+ cb(userdata, fullinst, inst->RGB.Src[src].File, inst->RGB.Src[src].Index,
+ refmasks[src] & RC_MASK_XYZ);
- if (inst->Alpha.Src[src].Used) {
- if (GET_BIT(refmasks[src], 3))
- cb(userdata, fullinst, inst->Alpha.Src[src].File, inst->Alpha.Src[src].Index, 3);
- }
+ if (inst->Alpha.Src[src].Used && (refmasks[src] & RC_MASK_W))
+ cb(userdata, fullinst, inst->Alpha.Src[src].File, inst->Alpha.Src[src].Index, RC_MASK_W);
}
}
/**
- * Calls a callback function for all sourced register channels.
+ * Calls a callback function for all register reads.
*
- * This is conservative, i.e. channels may be called multiple times,
- * and the writemask of the instruction is not taken into account.
+ * This is conservative, i.e. if the same register is referenced multiple times,
+ * the callback may also be called multiple times.
+ * Also, the writemask of the instruction is not taken into account.
*/
-void rc_for_all_reads(struct rc_instruction * inst, rc_read_write_fn cb, void * userdata)
+void rc_for_all_reads_mask(struct rc_instruction * inst, rc_read_write_mask_fn cb, void * userdata)
{
if (inst->Type == RC_INSTRUCTION_NORMAL) {
reads_normal(inst, cb, userdata);
-static void writes_normal(struct rc_instruction * fullinst, rc_read_write_fn cb, void * userdata)
+static void writes_normal(struct rc_instruction * fullinst, rc_read_write_mask_fn cb, void * userdata)
{
struct rc_sub_instruction * inst = &fullinst->U.I;
const struct rc_opcode_info * opcode = rc_get_opcode_info(inst->Opcode);
- if (opcode->HasDstReg) {
- for(unsigned int chan = 0; chan < 4; ++chan) {
- if (GET_BIT(inst->DstReg.WriteMask, chan))
- cb(userdata, fullinst, inst->DstReg.File, inst->DstReg.Index, chan);
- }
- }
+ if (opcode->HasDstReg && inst->DstReg.WriteMask)
+ cb(userdata, fullinst, inst->DstReg.File, inst->DstReg.Index, inst->DstReg.WriteMask);
if (inst->WriteALUResult)
- cb(userdata, fullinst, RC_FILE_SPECIAL, RC_SPECIAL_ALU_RESULT, 0);
+ cb(userdata, fullinst, RC_FILE_SPECIAL, RC_SPECIAL_ALU_RESULT, RC_MASK_X);
}
-static void writes_pair(struct rc_instruction * fullinst, rc_read_write_fn cb, void * userdata)
+static void writes_pair(struct rc_instruction * fullinst, rc_read_write_mask_fn cb, void * userdata)
{
struct rc_pair_instruction * inst = &fullinst->U.P;
- for(unsigned int chan = 0; chan < 3; ++chan) {
- if (GET_BIT(inst->RGB.WriteMask, chan))
- cb(userdata, fullinst, RC_FILE_TEMPORARY, inst->RGB.DestIndex, chan);
- }
+ if (inst->RGB.WriteMask)
+ cb(userdata, fullinst, RC_FILE_TEMPORARY, inst->RGB.DestIndex, inst->RGB.WriteMask);
if (inst->Alpha.WriteMask)
- cb(userdata, fullinst, RC_FILE_TEMPORARY, inst->Alpha.DestIndex, 3);
+ cb(userdata, fullinst, RC_FILE_TEMPORARY, inst->Alpha.DestIndex, RC_MASK_W);
if (inst->WriteALUResult)
- cb(userdata, fullinst, RC_FILE_SPECIAL, RC_SPECIAL_ALU_RESULT, 0);
+ cb(userdata, fullinst, RC_FILE_SPECIAL, RC_SPECIAL_ALU_RESULT, RC_MASK_X);
}
/**
- * Calls a callback function for all written register channels.
+ * Calls a callback function for all register writes in the instruction,
+ * reporting writemasks to the callback function.
*
* \warning Does not report output registers for paired instructions!
*/
-void rc_for_all_writes(struct rc_instruction * inst, rc_read_write_fn cb, void * userdata)
+void rc_for_all_writes_mask(struct rc_instruction * inst, rc_read_write_mask_fn cb, void * userdata)
{
if (inst->Type == RC_INSTRUCTION_NORMAL) {
writes_normal(inst, cb, userdata);
}
+struct mask_to_chan_data {
+ void * UserData;
+ rc_read_write_chan_fn Fn;
+};
+
+static void mask_to_chan_cb(void * data, struct rc_instruction * inst,
+ rc_register_file file, unsigned int index, unsigned int mask)
+{
+ struct mask_to_chan_data * d = data;
+ for(unsigned int chan = 0; chan < 4; ++chan) {
+ if (GET_BIT(mask, chan))
+ d->Fn(d->UserData, inst, file, index, chan);
+ }
+}
+
+/**
+ * Calls a callback function for all sourced register channels.
+ *
+ * This is conservative, i.e. channels may be called multiple times,
+ * and the writemask of the instruction is not taken into account.
+ */
+void rc_for_all_reads_chan(struct rc_instruction * inst, rc_read_write_chan_fn cb, void * userdata)
+{
+ struct mask_to_chan_data d;
+ d.UserData = userdata;
+ d.Fn = cb;
+ rc_for_all_reads_mask(inst, &mask_to_chan_cb, &d);
+}
+
+/**
+ * Calls a callback function for all written register channels.
+ *
+ * \warning Does not report output registers for paired instructions!
+ */
+void rc_for_all_writes_chan(struct rc_instruction * inst, rc_read_write_chan_fn cb, void * userdata)
+{
+ struct mask_to_chan_data d;
+ d.UserData = userdata;
+ d.Fn = cb;
+ rc_for_all_writes_mask(inst, &mask_to_chan_cb, &d);
+}
+
static void remap_normal_instruction(struct rc_instruction * fullinst,
rc_remap_register_fn cb, void * userdata)
{
* Help analyze and modify the register accesses of instructions.
*/
/*@{*/
-typedef void (*rc_read_write_fn)(void * userdata, struct rc_instruction * inst,
+typedef void (*rc_read_write_chan_fn)(void * userdata, struct rc_instruction * inst,
rc_register_file file, unsigned int index, unsigned int chan);
-void rc_for_all_reads(struct rc_instruction * inst, rc_read_write_fn cb, void * userdata);
-void rc_for_all_writes(struct rc_instruction * inst, rc_read_write_fn cb, void * userdata);
+void rc_for_all_reads_chan(struct rc_instruction * inst, rc_read_write_chan_fn cb, void * userdata);
+void rc_for_all_writes_chan(struct rc_instruction * inst, rc_read_write_chan_fn cb, void * userdata);
+
+typedef void (*rc_read_write_mask_fn)(void * userdata, struct rc_instruction * inst,
+ rc_register_file file, unsigned int index, unsigned int mask);
+void rc_for_all_reads_mask(struct rc_instruction * inst, rc_read_write_mask_fn cb, void * userdata);
+void rc_for_all_writes_mask(struct rc_instruction * inst, rc_read_write_mask_fn cb, void * userdata);
typedef void (*rc_remap_register_fn)(void * userdata, struct rc_instruction * inst,
rc_register_file * pfile, unsigned int * pindex);
void rc_dataflow_swizzles(struct radeon_compiler * c);
/*@}*/
+void rc_optimize(struct radeon_compiler * c);
+
#endif /* RADEON_DATAFLOW_H */
sap.Proxies = proxies;
for(struct rc_instruction * inst = begin; inst != end; inst = inst->Next) {
- rc_for_all_writes(inst, scan_write, &sap);
+ rc_for_all_writes_mask(inst, scan_write, &sap);
rc_remap_registers(inst, remap_proxy_function, &sap);
}
--- /dev/null
+/*
+ * Copyright (C) 2009 Nicolai Haehnle.
+ *
+ * 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 (including the
+ * next paragraph) shall be included in all copies or substantial
+ * portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#include "radeon_dataflow.h"
+
+#include "radeon_compiler.h"
+#include "radeon_swizzle.h"
+
+
+static struct rc_src_register chain_srcregs(struct rc_src_register outer, struct rc_src_register inner)
+{
+ struct rc_src_register combine;
+ combine.File = inner.File;
+ combine.Index = inner.Index;
+ combine.RelAddr = inner.RelAddr;
+ if (outer.Abs) {
+ combine.Abs = 1;
+ combine.Negate = outer.Negate;
+ } else {
+ combine.Abs = inner.Abs;
+ combine.Negate = 0;
+ for(unsigned int chan = 0; chan < 4; ++chan) {
+ unsigned int swz = GET_SWZ(outer.Swizzle, chan);
+ if (swz < 4)
+ combine.Negate |= GET_BIT(inner.Negate, swz) << chan;
+ }
+ combine.Negate ^= outer.Negate;
+ }
+ combine.Swizzle = combine_swizzles(inner.Swizzle, outer.Swizzle);
+ return combine;
+}
+
+struct peephole_state {
+ struct radeon_compiler * C;
+ struct rc_instruction * Mov;
+ unsigned int Conflict:1;
+
+ /** Whether Mov's source has been clobbered */
+ unsigned int SourceClobbered:1;
+
+ /** Which components of Mov's destination register are still from that Mov? */
+ unsigned int MovMask:4;
+
+ /** Which components of Mov's destination register are clearly *not* from that Mov */
+ unsigned int DefinedMask:4;
+
+ /** Which components of Mov's source register are sourced */
+ unsigned int SourcedMask:4;
+
+ /** Branch depth beyond Mov; negative value indicates we left the Mov's block */
+ int BranchDepth;
+};
+
+static void peephole_scan_read(void * data, struct rc_instruction * inst,
+ rc_register_file file, unsigned int index, unsigned int mask)
+{
+ struct peephole_state * s = data;
+
+ if (file != RC_FILE_TEMPORARY || index != s->Mov->U.I.DstReg.Index)
+ return;
+
+ /* These instructions cannot read from the constants file.
+ * see radeonTransformTEX()
+ */
+ if(s->Mov->U.I.SrcReg[0].File != RC_FILE_TEMPORARY &&
+ s->Mov->U.I.SrcReg[0].File != RC_FILE_INPUT &&
+ (inst->U.I.Opcode == RC_OPCODE_TEX ||
+ inst->U.I.Opcode == RC_OPCODE_TXB ||
+ inst->U.I.Opcode == RC_OPCODE_TXP ||
+ inst->U.I.Opcode == RC_OPCODE_KIL)){
+ s->Conflict = 1;
+ return;
+ }
+ if ((mask & s->MovMask) == mask) {
+ if (s->SourceClobbered) {
+ s->Conflict = 1;
+ }
+ } else if ((mask & s->DefinedMask) == mask) {
+ /* read from something entirely written by other instruction: this is okay */
+ } else {
+ /* read from component combination that is not well-defined without
+ * the MOV: cannot remove it */
+ s->Conflict = 1;
+ }
+}
+
+static void peephole_scan_write(void * data, struct rc_instruction * inst,
+ rc_register_file file, unsigned int index, unsigned int mask)
+{
+ struct peephole_state * s = data;
+
+ if (s->BranchDepth < 0)
+ return;
+
+ if (file == s->Mov->U.I.DstReg.File && index == s->Mov->U.I.DstReg.Index) {
+ s->MovMask &= ~mask;
+ if (s->BranchDepth == 0)
+ s->DefinedMask |= mask;
+ else
+ s->DefinedMask &= ~mask;
+ }
+ if (file == s->Mov->U.I.SrcReg[0].File && index == s->Mov->U.I.SrcReg[0].Index) {
+ if (mask & s->SourcedMask)
+ s->SourceClobbered = 1;
+ } else if (s->Mov->U.I.SrcReg[0].RelAddr && file == RC_FILE_ADDRESS) {
+ s->SourceClobbered = 1;
+ }
+}
+
+static void peephole(struct radeon_compiler * c, struct rc_instruction * inst_mov)
+{
+ struct peephole_state s;
+
+ if (inst_mov->U.I.DstReg.File != RC_FILE_TEMPORARY || inst_mov->U.I.WriteALUResult)
+ return;
+
+ memset(&s, 0, sizeof(s));
+ s.C = c;
+ s.Mov = inst_mov;
+ s.MovMask = inst_mov->U.I.DstReg.WriteMask;
+ s.DefinedMask = RC_MASK_XYZW & ~s.MovMask;
+
+ for(unsigned int chan = 0; chan < 4; ++chan) {
+ unsigned int swz = GET_SWZ(inst_mov->U.I.SrcReg[0].Swizzle, chan);
+ s.SourcedMask |= (1 << swz) & RC_MASK_XYZW;
+ }
+
+ /* 1st pass: Check whether all subsequent readers can be changed */
+ for(struct rc_instruction * inst = inst_mov->Next;
+ inst != &c->Program.Instructions;
+ inst = inst->Next) {
+ rc_for_all_reads_mask(inst, peephole_scan_read, &s);
+ rc_for_all_writes_mask(inst, peephole_scan_write, &s);
+ if (s.Conflict)
+ return;
+
+ if (s.BranchDepth >= 0) {
+ if (inst->U.I.Opcode == RC_OPCODE_IF) {
+ s.BranchDepth++;
+ } else if (inst->U.I.Opcode == RC_OPCODE_ENDIF) {
+ s.BranchDepth--;
+ if (s.BranchDepth < 0) {
+ s.DefinedMask &= ~s.MovMask;
+ s.MovMask = 0;
+ }
+ }
+ }
+ }
+
+ if (s.Conflict)
+ return;
+
+ /* 2nd pass: We can satisfy all readers, so switch them over all at once */
+ s.MovMask = inst_mov->U.I.DstReg.WriteMask;
+ s.BranchDepth = 0;
+
+ for(struct rc_instruction * inst = inst_mov->Next;
+ inst != &c->Program.Instructions;
+ inst = inst->Next) {
+ const struct rc_opcode_info * opcode = rc_get_opcode_info(inst->U.I.Opcode);
+
+ for(unsigned int src = 0; src < opcode->NumSrcRegs; ++src) {
+ if (inst->U.I.SrcReg[src].File == RC_FILE_TEMPORARY &&
+ inst->U.I.SrcReg[src].Index == s.Mov->U.I.DstReg.Index) {
+ unsigned int refmask = 0;
+
+ for(unsigned int chan = 0; chan < 4; ++chan) {
+ unsigned int swz = GET_SWZ(inst->U.I.SrcReg[src].Swizzle, chan);
+ refmask |= (1 << swz) & RC_MASK_XYZW;
+ }
+
+ if ((refmask & s.MovMask) == refmask)
+ inst->U.I.SrcReg[src] = chain_srcregs(inst->U.I.SrcReg[src], s.Mov->U.I.SrcReg[0]);
+ }
+ }
+
+ if (opcode->HasDstReg) {
+ if (inst->U.I.DstReg.File == RC_FILE_TEMPORARY &&
+ inst->U.I.DstReg.Index == s.Mov->U.I.DstReg.Index) {
+ s.MovMask &= ~inst->U.I.DstReg.WriteMask;
+ }
+ }
+
+ if (s.BranchDepth >= 0) {
+ if (inst->U.I.Opcode == RC_OPCODE_IF) {
+ s.BranchDepth++;
+ } else if (inst->U.I.Opcode == RC_OPCODE_ENDIF) {
+ s.BranchDepth--;
+ if (s.BranchDepth < 0)
+ break; /* no more readers after this point */
+ }
+ }
+ }
+
+ /* Finally, remove the original MOV instruction */
+ rc_remove_instruction(inst_mov);
+}
+
+/**
+ * Check if a source register is actually always the same
+ * swizzle constant.
+ */
+static int is_src_uniform_constant(struct rc_src_register src,
+ rc_swizzle * pswz, unsigned int * pnegate)
+{
+ int have_used = 0;
+
+ if (src.File != RC_FILE_NONE) {
+ *pswz = 0;
+ return 0;
+ }
+
+ for(unsigned int chan = 0; chan < 4; ++chan) {
+ unsigned int swz = GET_SWZ(src.Swizzle, chan);
+ if (swz < 4) {
+ *pswz = 0;
+ return 0;
+ }
+ if (swz == RC_SWIZZLE_UNUSED)
+ continue;
+
+ if (!have_used) {
+ *pswz = swz;
+ *pnegate = GET_BIT(src.Negate, chan);
+ have_used = 1;
+ } else {
+ if (swz != *pswz || *pnegate != GET_BIT(src.Negate, chan)) {
+ *pswz = 0;
+ return 0;
+ }
+ }
+ }
+
+ return 1;
+}
+
+
+static void constant_folding_mad(struct rc_instruction * inst)
+{
+ rc_swizzle swz;
+ unsigned int negate;
+
+ if (is_src_uniform_constant(inst->U.I.SrcReg[2], &swz, &negate)) {
+ if (swz == RC_SWIZZLE_ZERO) {
+ inst->U.I.Opcode = RC_OPCODE_MUL;
+ return;
+ }
+ }
+
+ if (is_src_uniform_constant(inst->U.I.SrcReg[1], &swz, &negate)) {
+ if (swz == RC_SWIZZLE_ONE) {
+ inst->U.I.Opcode = RC_OPCODE_ADD;
+ if (negate)
+ inst->U.I.SrcReg[0].Negate ^= RC_MASK_XYZW;
+ inst->U.I.SrcReg[1] = inst->U.I.SrcReg[2];
+ return;
+ } else if (swz == RC_SWIZZLE_ZERO) {
+ inst->U.I.Opcode = RC_OPCODE_MOV;
+ inst->U.I.SrcReg[0] = inst->U.I.SrcReg[2];
+ return;
+ }
+ }
+
+ if (is_src_uniform_constant(inst->U.I.SrcReg[0], &swz, &negate)) {
+ if (swz == RC_SWIZZLE_ONE) {
+ inst->U.I.Opcode = RC_OPCODE_ADD;
+ if (negate)
+ inst->U.I.SrcReg[1].Negate ^= RC_MASK_XYZW;
+ inst->U.I.SrcReg[0] = inst->U.I.SrcReg[2];
+ return;
+ } else if (swz == RC_SWIZZLE_ZERO) {
+ inst->U.I.Opcode = RC_OPCODE_MOV;
+ inst->U.I.SrcReg[0] = inst->U.I.SrcReg[2];
+ return;
+ }
+ }
+}
+
+static void constant_folding_mul(struct rc_instruction * inst)
+{
+ rc_swizzle swz;
+ unsigned int negate;
+
+ if (is_src_uniform_constant(inst->U.I.SrcReg[0], &swz, &negate)) {
+ if (swz == RC_SWIZZLE_ONE) {
+ inst->U.I.Opcode = RC_OPCODE_MOV;
+ inst->U.I.SrcReg[0] = inst->U.I.SrcReg[1];
+ if (negate)
+ inst->U.I.SrcReg[0].Negate ^= RC_MASK_XYZW;
+ return;
+ } else if (swz == RC_SWIZZLE_ZERO) {
+ inst->U.I.Opcode = RC_OPCODE_MOV;
+ inst->U.I.SrcReg[0].Swizzle = RC_SWIZZLE_0000;
+ return;
+ }
+ }
+
+ if (is_src_uniform_constant(inst->U.I.SrcReg[1], &swz, &negate)) {
+ if (swz == RC_SWIZZLE_ONE) {
+ inst->U.I.Opcode = RC_OPCODE_MOV;
+ if (negate)
+ inst->U.I.SrcReg[0].Negate ^= RC_MASK_XYZW;
+ return;
+ } else if (swz == RC_SWIZZLE_ZERO) {
+ inst->U.I.Opcode = RC_OPCODE_MOV;
+ inst->U.I.SrcReg[0].Swizzle = RC_SWIZZLE_0000;
+ return;
+ }
+ }
+}
+
+static void constant_folding_add(struct rc_instruction * inst)
+{
+ rc_swizzle swz;
+ unsigned int negate;
+
+ if (is_src_uniform_constant(inst->U.I.SrcReg[0], &swz, &negate)) {
+ if (swz == RC_SWIZZLE_ZERO) {
+ inst->U.I.Opcode = RC_OPCODE_MOV;
+ inst->U.I.SrcReg[0] = inst->U.I.SrcReg[1];
+ return;
+ }
+ }
+
+ if (is_src_uniform_constant(inst->U.I.SrcReg[1], &swz, &negate)) {
+ if (swz == RC_SWIZZLE_ZERO) {
+ inst->U.I.Opcode = RC_OPCODE_MOV;
+ return;
+ }
+ }
+}
+
+
+/**
+ * Replace 0.0, 1.0 and 0.5 immediate constants by their
+ * respective swizzles. Simplify instructions like ADD dst, src, 0;
+ */
+static void constant_folding(struct radeon_compiler * c, struct rc_instruction * inst)
+{
+ const struct rc_opcode_info * opcode = rc_get_opcode_info(inst->U.I.Opcode);
+
+ /* Replace 0.0, 1.0 and 0.5 immediates by their explicit swizzles */
+ for(unsigned int src = 0; src < opcode->NumSrcRegs; ++src) {
+ if (inst->U.I.SrcReg[src].File != RC_FILE_CONSTANT ||
+ inst->U.I.SrcReg[src].RelAddr ||
+ inst->U.I.SrcReg[src].Index >= c->Program.Constants.Count)
+ continue;
+
+ struct rc_constant * constant =
+ &c->Program.Constants.Constants[inst->U.I.SrcReg[src].Index];
+
+ if (constant->Type != RC_CONSTANT_IMMEDIATE)
+ continue;
+
+ struct rc_src_register newsrc = inst->U.I.SrcReg[src];
+ int have_real_reference = 0;
+ for(unsigned int chan = 0; chan < 4; ++chan) {
+ unsigned int swz = GET_SWZ(newsrc.Swizzle, chan);
+ if (swz >= 4)
+ continue;
+
+ unsigned int newswz;
+ float imm = constant->u.Immediate[swz];
+ float baseimm = imm;
+ if (imm < 0.0)
+ baseimm = -baseimm;
+
+ if (baseimm == 0.0) {
+ newswz = RC_SWIZZLE_ZERO;
+ } else if (baseimm == 1.0) {
+ newswz = RC_SWIZZLE_ONE;
+ } else if (baseimm == 0.5) {
+ newswz = RC_SWIZZLE_HALF;
+ } else {
+ have_real_reference = 1;
+ continue;
+ }
+
+ SET_SWZ(newsrc.Swizzle, chan, newswz);
+ if (imm < 0.0 && !newsrc.Abs)
+ newsrc.Negate ^= 1 << chan;
+ }
+
+ if (!have_real_reference) {
+ newsrc.File = RC_FILE_NONE;
+ newsrc.Index = 0;
+ }
+
+ /* don't make the swizzle worse */
+ if (!c->SwizzleCaps->IsNative(inst->U.I.Opcode, newsrc) &&
+ c->SwizzleCaps->IsNative(inst->U.I.Opcode, inst->U.I.SrcReg[src]))
+ continue;
+
+ inst->U.I.SrcReg[src] = newsrc;
+ }
+
+ /* Simplify instructions based on constants */
+ if (inst->U.I.Opcode == RC_OPCODE_MAD)
+ constant_folding_mad(inst);
+
+ /* note: MAD can simplify to MUL or ADD */
+ if (inst->U.I.Opcode == RC_OPCODE_MUL)
+ constant_folding_mul(inst);
+ else if (inst->U.I.Opcode == RC_OPCODE_ADD)
+ constant_folding_add(inst);
+}
+
+void rc_optimize(struct radeon_compiler * c)
+{
+ struct rc_instruction * inst = c->Program.Instructions.Next;
+ while(inst != &c->Program.Instructions) {
+ struct rc_instruction * cur = inst;
+ inst = inst->Next;
+
+ constant_folding(c, cur);
+
+ if (cur->U.I.Opcode == RC_OPCODE_MOV) {
+ peephole(c, cur);
+ /* cur may no longer be part of the program */
+ }
+ }
+}
}
static void scan_callback(void * data, struct rc_instruction * inst,
- rc_register_file file, unsigned int index, unsigned int chan)
+ rc_register_file file, unsigned int index, unsigned int mask)
{
struct regalloc_state * s = data;
struct register_info * reg;
for(struct rc_instruction * inst = s->C->Program.Instructions.Next;
inst != &s->C->Program.Instructions;
inst = inst->Next) {
- rc_for_all_reads(inst, scan_callback, s);
- rc_for_all_writes(inst, scan_callback, s);
+ rc_for_all_reads_mask(inst, scan_callback, s);
+ rc_for_all_writes_mask(inst, scan_callback, s);
}
}
* counter-intuitive, to account for the case where an
* instruction writes to the same register as it reads
* from. */
- rc_for_all_writes(inst, &scan_write, &s);
- rc_for_all_reads(inst, &scan_read, &s);
+ rc_for_all_writes_chan(inst, &scan_write, &s);
+ rc_for_all_reads_chan(inst, &scan_read, &s);
DBG("%i: Has %i dependencies\n", inst->IP, s.Current->NumDependencies);
struct rc_instruction * inst_cmp;
unsigned tmp_texsample = rc_find_free_temporary(c);
unsigned tmp_sum = rc_find_free_temporary(c);
- unsigned tmp_recip_w;
+ unsigned tmp_recip_w = 0;
int pass, fail, tex;
/* Save the output register. */
GenericFunc
_mesa_dlsym(void *handle, const char *fname)
{
+ union {
+ void *v;
+ GenericFunc f;
+ } u;
#if defined(__blrts)
- return (GenericFunc) NULL;
+ u.v = NULL;
#elif defined(__DJGPP__)
/* need '_' prefix on symbol names */
char fname2[1000];
fname2[0] = '_';
strncpy(fname2 + 1, fname, 998);
fname2[999] = 0;
- return (GenericFunc) dlsym(handle, fname2);
+ u.v = dlsym(handle, fname2);
#elif defined(_GNU_SOURCE)
- return (GenericFunc) dlsym(handle, fname);
+ u.v = dlsym(handle, fname);
#elif defined(__MINGW32__)
- return (GenericFunc) GetProcAddress(handle, fname);
+ u.v = (void *) GetProcAddress(handle, fname);
#else
- return (GenericFunc) NULL;
+ u.v = NULL;
#endif
+ return u.f;
}
#include "main/state.h"
#include "main/imports.h"
-#include "main/dispatch.h"
-
#if FEATURE_OES_draw_texture
#include "glheader.h"
#include "context.h"
#include "enable.h"
+#include "enums.h"
#include "extensions.h"
#include "get.h"
#include "macros.h"
struct value_desc {
GLenum pname;
- enum value_location location : 8;
- enum value_type type : 8;
+ GLubyte location; /**< enum value_location */
+ GLubyte type; /**< enum value_type */
int offset;
const int *extra;
};
}
if (total > 0 && enabled == 0) {
- _mesa_error(ctx, GL_INVALID_ENUM, "%s(pname=0x%x)", func, d->pname);
+ _mesa_error(ctx, GL_INVALID_ENUM, "%s(pname=%s)", func,
+ _mesa_lookup_enum_by_nr(d->pname));
return GL_FALSE;
}
/* If the enum isn't valid, the hash walk ends with index 0,
* which is the API mask entry at the beginning of values[]. */
if (d->type == TYPE_API_MASK) {
- _mesa_error(ctx, GL_INVALID_ENUM, "%s(pname=0x%x)", func, pname);
+ _mesa_error(ctx, GL_INVALID_ENUM, "%s(pname=%s)", func,
+ _mesa_lookup_enum_by_nr(pname));
return &error_value;
}
hash += prime_step;
}
invalid_enum:
- _mesa_error(ctx, GL_INVALID_ENUM, "%s(pname=0x%x)", func, pname);
+ _mesa_error(ctx, GL_INVALID_ENUM, "%s(pname=%s)", func,
+ _mesa_lookup_enum_by_nr(pname));
return TYPE_INVALID;
invalid_value:
- _mesa_error(ctx, GL_INVALID_VALUE, "%s(pname=0x%x)", func, pname);
+ _mesa_error(ctx, GL_INVALID_VALUE, "%s(pname=%s)", func,
+ _mesa_lookup_enum_by_nr(pname));
return TYPE_INVALID;
}
}
}
-#elif defined(__APPLE__) || defined(__CYGWIN__)
+#elif defined(__APPLE__) || defined(__CYGWIN__) || defined(__FreeBSD__) || \
+ (defined(__sun) && defined(__C99FEATURES__))
/* fpclassify is available. */
/* Delete the default feedback object */
assert(ctx->Driver.DeleteTransformFeedback);
- ctx->Driver.DeleteTransformFeedback(ctx, ctx->TransformFeedback.DefaultObject);
+ ctx->Driver.DeleteTransformFeedback(ctx,
+ ctx->TransformFeedback.DefaultObject);
ctx->TransformFeedback.CurrentObject = NULL;
}
if (ctx->TransformFeedback.CurrentObject->Active &&
!ctx->TransformFeedback.CurrentObject->Paused) {
_mesa_error(ctx, GL_INVALID_OPERATION,
- "glBindTransformFeedback(transform is active, or not paused)");
+ "glBindTransformFeedback(transform is active, or not paused)");
return;
}
if (!obj->Active || !obj->Paused) {
_mesa_error(ctx, GL_INVALID_OPERATION,
- "glPauseTransformFeedback(feedback not active or not paused)");
+ "glPauseTransformFeedback(feedback not active or not paused)");
return;
}
struct gl_transform_feedback_object *obj =
lookup_transform_feedback_object(ctx, name);
+ if (mode > GL_POLYGON) {
+ _mesa_error(ctx, GL_INVALID_ENUM,
+ "glDrawTransformFeedback(mode=0x%x)", mode);
+ return;
+ }
if (!obj) {
_mesa_error(ctx, GL_INVALID_VALUE,
"glDrawTransformFeedback(name = %u)", name);
/* check that the sampler (tex unit index) is legal */
if (texUnit >= ctx->Const.MaxTextureImageUnits) {
_mesa_error(ctx, GL_INVALID_VALUE,
- "glUniform1(invalid sampler/tex unit index)");
+ "glUniform1(invalid sampler/tex unit index for '%s')",
+ param->Name);
return;
}
/* non-array: count must be at most one; count == 0 is handled by the loop below */
if (count > 1) {
_mesa_error(ctx, GL_INVALID_OPERATION,
- "glUniform(uniform is not an array)");
+ "glUniform(uniform '%s' is not an array)",
+ param->Name);
return;
}
}
return; /* The standard specifies this as a no-op */
if (location < -1) {
- _mesa_error(ctx, GL_INVALID_OPERATION, "glUniform(location)");
+ _mesa_error(ctx, GL_INVALID_OPERATION, "glUniform(location=%d)",
+ location);
return;
}
split_location_offset(&location, &offset);
if (location < 0 || location >= (GLint) shProg->Uniforms->NumUniforms) {
- _mesa_error(ctx, GL_INVALID_VALUE, "glUniform(location)");
+ _mesa_error(ctx, GL_INVALID_VALUE, "glUniform(location=%d)", location);
return;
}
case GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN:
type = PIPE_QUERY_PRIMITIVES_EMITTED;
break;
+ case GL_TIME_ELAPSED_EXT:
+ type = PIPE_QUERY_TIME_ELAPSED;
+ break;
default:
assert(0 && "unexpected query target in st_BeginQuery()");
return;
#include "st_debug.h"
#include "st_context.h"
#include "st_atom.h"
+#include "st_cb_bitmap.h"
#include "st_cb_readpixels.h"
#include "st_cb_fbo.h"
return;
}
+ st_flush_bitmap_cache(st);
+
dest = _mesa_map_pbo_dest(ctx, &clippedPacking, dest);
if (!dest)
return;
if (screen->get_param(screen, PIPE_CAP_OCCLUSION_QUERY)) {
ctx->Extensions.ARB_occlusion_query = GL_TRUE;
}
+ if (screen->get_param(screen, PIPE_CAP_TIMER_QUERY)) {
+ ctx->Extensions.EXT_timer_query = GL_TRUE;
+ }
if (screen->get_param(screen, PIPE_CAP_TEXTURE_SHADOW_MAP)) {
ctx->Extensions.ARB_depth_texture = GL_TRUE;